现在已经不断有网友发我他们在面试中遇到的面试题,这是一位程序媛前面在面试中遇到的问题
前面两个过于基础,从提高题开始分享;个人见解,勿喷
代理的的是改变或传递控制链。允许个类在某些特定时刻通知到其他类,而需要获取到那些类的指针。可以减少框架复杂度。
什么是代理?
代理是种通的设计模式,代理主要由三部分组成
一、协议:用来指定代双方可以做么,必须做么;
二、代:根据指定的协议,完成委托需要实现的功能;
三、委托:根据指定的协议,指定代理去完成么功能。
代理的实现流程
在iOS中代的本质就是代理对象内存的传递和操作,我们在委托类设置代理对象后,实际上只是一个id类型的指针将代理对象进了一个弱引。委托让代理方执操作,实际上是在委托类中向这个id类型指针指向的对象发送消息,这个id类型指针指向的对象,就是代理对象。
代理的内存管理
使代理如果声明的对,会造成循环引的问题。般会
weak
修饰,
strong
修饰会造成循环引问题,
assign
修饰会造成
crash
。
代理与其他iOS中消息传递的式的对
通知:在iOS中由通知中进消息接收和消息播,是种对多的消息传递式。
代理:是种通的设计模式,iOS中对代理持的很好,由代理对象、委托者、协议三部分组成。
Block
:
iOS4.0
中引的种回调法,可以将回调处理代码直接写在
block
代码块中,看起来逻辑清晰代码整。
target action
:通过将对象传递到另个类中,在另个类中将该对象当做
target
的式,来调该对象法,从内存度来说和代理类似。
KVO
NSObject
的
Category-NSKeyValueObserving
,通过属性监听的式来监测某个值的变化,当值发变化时调
KVO
的回调法。
代理与 block
的对
block
1.多个消息传递,应该使delegate。在有多个消息传递时,
delegate
实现更合适,看起来也更清晰。
block
就不太好了,这个时候
block
反而便于维护,且看起来常臃肿,很别扭。例如
UIKit
UITableView
中有很多代理如果都换成
block
实现,会比
delegates
难好多。
2.一个委托对象的代理属性只能有个代理对象,如果想要委托对象调多个代理对象的回调应该用block。
3.单例对象最好不要
delegate
。单例对象由于始终都只是同个对象,如果使
delegate
,就会造成
delegate
属性被重新赋值的问题,最终只能有一个对象可以正常响应代法。
4.代理更加相过程,
block
则更面向结果。从设计模式的角度来说,代理更加面向过程,
block
更加向结果。
5.从性能上来说,
block
的性能消耗要略大于
delegate
,因为
block
会涉及到栈区向堆区拷等操作,时间和空间上的消耗都于代理。代只是定义了个法列表,在遵守协议对象的
objc_protocol_list
中添加个节点,在运时向遵守协议的对象发送消息即可
题二: Objective C
中多重继承的实现机制。
Objective C
什么是多继承?
假设C类要同时继承A类和B类,则称之为多继承。这种情况就是多继承。
oc中的“多继承”
其实
Objective-C
不支持多继承,由于消息机制名字查找发在运时非编译时,很难解决多个基类可能导致的义性问题。不过其实
Objective-C
也需持多继承,我们可以找到如下种间接实现多继承的方法:
- 通过组合实现“多继承”
- 通过协议实现“多继承”
通过协议实现“多继承
虽然OC在语法上禁类使多继承,但是却可以协议来实现多继承。协议只能提供接,而没有提供实现式,如果只是想多继承基类的接,那么遵守多协议疑是最好的法。
此法缺点较明显:需要修改两个类,同时并不能调两个类的原法,需要在类中实现法。
题三:简述 Singleton
的概念及并使用 Objective C
写出相关代码。
Singleton
Objective C
Singleton: 单例模式。 简单来说, 就是保证在你不主动销毁这个单例对象的情况下, 整个项目中都始终拥有这个单例对象, 并且这个单例对象在内存中都是同一个内存地址。
所以, 单例很重要的两个特点:
(1) app生命周期中一直存在(除主动销毁外)
(2) 在整个生命周期中, 都是同一个内存地址
根据这两个特点, 我来描述一个应用中的使用场景。 最简单和常用的就是, 我们用户的登录信息, 不做本地缓存的话, 我们登录成功之后, 把服务器请求下来的用户信息保存到单例中。 比如这样
[UserSingletonshareInstance].name = “张山”
。 接下来, 你无论在应用的任何页面都可以直接通过[UserSingleton shareInstance].name的方式获取到用户的名字, 而且这个名字都是”张三”。 其他做法,都会比这个麻烦。
那么怎么写单例呢? 核心的一点就是, 我们平时创建一个实例对象时候用到的方法(
alloc, init
), 都要重写一遍,保证使用这些方法创建对象的时候是只分配一块内存地址,然后第一次创建之后再创建都指向前边已经创建过得那个内存地址,顺着这个思路,代码如下:
然后,OC有个语法糖可以写:
题四:简述 @selector
的作用
@selector
Selector/SEL
又叫方法选择器,
SEL在objc.h
中是这样声明的,而“
@selector()
”是取得一个
SEL
指针。说白了,方法选择器仅仅是一个
char *
指针,表示它所代表的是方法的名字。 简单来说: “
@Selector
就是用字符串表示某个类的某个方法。” 更加专业的说法是: “
Selector
就是OC的虚拟表(
virtual table
)中指向实际执行的函数指针(
function pointer
)的一个C字符。”
我们一般用它来“因为
method
可以用字符串表示,因此,某个
method
就可以变成用来传递的参数。” 再说的透明一点, 因为
selector
可以看做是函数的另一个名字,所以很多需要调用函数或者建立连接的地方,都可以用到,以下是一些具体的使用场景:
-
模式Target/Action
- 检查
是否存在method
-
Timer
- 在线程中执行方法
- 数组排序
- 代替
if else / switch
- 调用私有
API
推荐 :
- 020 持续更新,精品小圈子每日都有新内容,干货浓度极高。
- 结实人脉、讨论技术 你想要的这里都有!
- 抢先入群,跑赢同龄人!(入群无需任何费用)
- 点击此处,与iOS开发大牛一起交流学习
申请即送:
- BAT大厂面试题、独家面试工具包,
- 资料免费领取,包括 数据结构、底层进阶、图形视觉、音视频、架构设计、逆向安防、RxSwift、flutter,