现在已经不断有网友发我他们在面试中遇到的面试题,这是一位程序媛前面在面试中遇到的问题
前面两个过于基础,从提高题开始分享;个人见解,勿喷
代理的的是改变或传递控制链。允许个类在某些特定时刻通知到其他类,而需要获取到那些类的指针。可以减少框架复杂度。
什么是代理?
代理是种通的设计模式,代理主要由三部分组成
一、协议:用来指定代双方可以做么,必须做么;
二、代:根据指定的协议,完成委托需要实现的功能;
三、委托:根据指定的协议,指定代理去完成么功能。
代理的实现流程
在iOS中代的本质就是代理对象内存的传递和操作,我们在委托类设置代理对象后,实际上只是一个id类型的指针将代理对象进了一个弱引。委托让代理方执操作,实际上是在委托类中向这个id类型指针指向的对象发送消息,这个id类型指针指向的对象,就是代理对象。
代理的内存管理
使代理如果声明的对,会造成循环引的问题。般会weak
修饰,strong
修饰会造成循环引问题,assign
修饰会造成crash
。
代理与其他iOS中消息传递的式的对
通知:在iOS中由通知中进消息接收和消息播,是种对多的消息传递式。
代理:是种通的设计模式,iOS中对代理持的很好,由代理对象、委托者、协议三部分组成。
Block
:iOS4.0
中引的种回调法,可以将回调处理代码直接写在block
代码块中,看起来逻辑清晰代码整。
target action
:通过将对象传递到另个类中,在另个类中将该对象当做target
的式,来调该对象法,从内存度来说和代理类似。
KVO
:NSObject
的Category-NSKeyValueObserving
,通过属性监听的式来监测某个值的变化,当值发变化时调KVO
的回调法。
代理与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
中多重继承的实现机制。
什么是多继承?
假设C类要同时继承A类和B类,则称之为多继承。这种情况就是多继承。
oc中的“多继承”
其实Objective-C
不支持多继承,由于消息机制名字查找发在运时非编译时,很难解决多个基类可能导致的义性问题。不过其实Objective-C
也需持多继承,我们可以找到如下种间接实现多继承的方法:
- 通过组合实现“多继承”
- 通过协议实现“多继承”
通过组合实现“多继承”
通过协议实现“多继承
虽然OC在语法上禁类使多继承,但是却可以协议来实现多继承。协议只能提供接,而没有提供实现式,如果只是想多继承基类的接,那么遵守多协议疑是最好的法。
此法缺点较明显:需要修改两个类,同时并不能调两个类的原法,需要在类中实现法。
题三:简述Singleton
的概念及并使用Objective C
写出相关代码。
Singleton: 单例模式。 简单来说, 就是保证在你不主动销毁这个单例对象的情况下, 整个项目中都始终拥有这个单例对象, 并且这个单例对象在内存中都是同一个内存地址。
所以, 单例很重要的两个特点:
(1) app生命周期中一直存在(除主动销毁外)
(2) 在整个生命周期中, 都是同一个内存地址
根据这两个特点, 我来描述一个应用中的使用场景。 最简单和常用的就是, 我们用户的登录信息, 不做本地缓存的话, 我们登录成功之后, 把服务器请求下来的用户信息保存到单例中。 比如这样[UserSingletonshareInstance].name = “张山”
。 接下来, 你无论在应用的任何页面都可以直接通过UserSingleton shareInstance.name的方式获取到用户的名字, 而且这个名字都是”张三”。 其他做法,都会比这个麻烦。
那么怎么写单例呢? 核心的一点就是, 我们平时创建一个实例对象时候用到的方法(alloc, init
), 都要重写一遍,保证使用这些方法创建对象的时候是只分配一块内存地址,然后第一次创建之后再创建都指向前边已经创建过得那个内存地址,顺着这个思路,代码如下:
然后,OC有个语法糖可以写:
题四:简述@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