一、weak和assign有什么区别 修饰delegate的属性是weak还是assign比较好?
答:assign是指针赋值 不对引用计数操作 使用了以后如果没有置为nil 可能会产生野指针
而weak一旦不进行使用后 永远不会再用了 weak会更安全一些
修饰delegate的属性可以用weak也可以用assign 但是weak比assign多了一个功能 就是当属性所指
向的对象消失的时候(内存引用计数为0)会自动赋值为nil 这样就不会产生野指针
二、OC作为一门面向对象的语言 具有面向对象的语言特性:继承 多态 封装
OC具有静态语言的特性 又具有动态语言的效率
三、什么是runtime
答:runtime是OC底层的一套C语言的API 编译器最终都会将OC代码转化为运行时的代码
runtime简称运行时 就是系统在运行的时候的一些机制 其中最主要的消息机制 对于C语言 函数的
调用在编译的时候会决定调用哪个函数 编译完成之后直接顺序执行 无任何二义性 OC的函数调用
成为消息发送 属于动态调用过程 在编译的时候并不能决定真正调用哪个函数 只有在真正运行的时
候才会根据函数的名称找到对应的函数来调用
那么OC是怎么实现动态调用的呢?下面来看看OC通过发送消息来达到动态调用的秘密
假设在OC中写了一段代码:[obj makeText];
其中obj就是一个对象 makeText事一个函数名称 对于这样一个简单的调用 在编译时Runtime会将上述代码转换成:objc_msgSend(obj,@selector(makeText));
首先我们来看看这个obj对象 iOS中的obj都继承于NSObject
@interface NSObject <nsobject>{
Class isa OBJC_ISA_AVAILABLITY;
}</nsobject>
在NSObject中存在一个Class的isa指针 然后我们看看Class
Class isa;//指向metaclass(元类) 也就是静态的Class 一般一个Obj对象中的isa会指向普通的Class 这个Class中存储普通成员变量和对象方法(“-”开头的方法) 普通Class中的isa指针指向静态Class 静态Class中存储static类型成员变量和类方法(“+”开头的方法)
Class super_class;//指向其父类 如果这个类时跟类 则为NULL
const char *name;//类名
long version;// 类的版本信息 初始化默认为0 可以通过runtime函数class setVersion和class getVersion进行修改 读取
long info;//一些标识信息 如CLS CLASS (0x1L)表示该类为普通class 其中包含对象方法和成员变量; CLS_META(0x2L)表示该类为metaclass 其中包含类方法
long instance_size;//该类的实例变量大小(包括服父类继承下来的实例变量)
struct objc_ivar_list *ivars;//用于存储每个成员变量的地址
struct objc_method_list **methodLists;//与info的一些标志位有关 如CLS_CLASS(0x1L),则存储对象方法 如CLS_META(0x2L) 则存储类方法
struct objc_cache *cache;//指向最近使用的方法的指针 用于提升效率
struct objc_protocol_list *protocols;//存储该类遵守的协议
@selector(makeText):这是一个SEL方法选择器 SEL其主要作用是快速的通过方法名字
(makeText)查找对应方法的函数指针 然后调用其函数 SEL其本身是一个Int类型的一个地址 地
址中存放着方法的名字 对于一个类中 每一个方法对应一个SEL 所以iOS类中不能存在2个名称相同
的方法 即使参数类型不同 因为SEL是根据方法名字生成的 相同的方法名称只能对应一个SEL
最后来看看具体消息发送之后是怎么来动态查找对应方法的
首先 编译器将代码[obj makeText];转化为objc_msgSend(obj,@selector(make Text)); 在
objc_msgSend函数中 首先通过obj的isa指针找到obj对应的class 在Class中先去cache中 通过SEL
查找对应函数method(猜测cache中method列表是以SEL为key通过hash表来存储的 这样能提高函
数查找速度) 若cache中未找到 再去methodList中查找 若methodList中未找到 则去superClass中查
找 若能找到 则将method加入到cache中 以方便下次找到 并通过method中的函数指针跳转到对应
的函数中去执行
四、weak与strong使用的区别
weak和strong不同的是 当一个对象不再有strong类型的指针指向它的时候 它就会被释放 即使
weak型指针指向它
一旦最后一个strong型的指针离去 这个对象将被对象释放 所有剩余的weak型的指针都将被清除
打个比方:想象我们的对象是一条狗 狗想要跑掉 strong型的指针就像是拴住的狗 只要你用牵绳拴
住狗 狗就不会被跑掉 如果有5个人牵着一条狗(5个strong型指针指向1个对象) 除非5个牵绳都脱
落 否则狗是不会跑掉的
weak型指针就像是一个小孩指着狗喊到:看 一只狗在哪里 只要狗一直被拴着 小孩就能看到狗
weak指针 会一直指向它 只要狗的牵绳脱落 狗就会跑掉 不管有多少小孩在看着它
只要最后一个strong型指针不再指向对象 那么对象就会被释放 同时所有的weak型指针都将会被清
除
如果零弱引用指向的对象被deallocated的话 零弱引用的对象会自动设置为nil
强引用与弱引用的广义区别:强引用也就是我们通常所讲的引用 其存亡直接决定了所指向对象的
存亡 如果不存在指向一个对象的引用 并且此对象不再显示列表中 则此内存会被内存中释放
弱引用除了不决定对象的存亡外 其他与强引用相同 即使一个对象被持有无数个弱引用 只要没有强
引用指向他 那么还是会被清除
五、property可以提供的功能有
1.提供成员变量的访问声明
2.控制成员变量的访问权限
3.控制多线程时成员变量的访问环境
4.property不但可以在interface 在协议和类别中也可以使用
synthesize:实现property所有声明的方法定义 简而言之就是property声明了一些成员变量的访问
方法 synthesize则定义了由property声明的方法
六、strong和retain的区别
strong和retain方法在MRC中的区别是:用retain 有时候.self会出现问题
1.如果返回的对象不是自动释放对象 我们不要用self.初始化对象
2.如果返回的对象是自动释放对象 我们最好用self来初始化一个对象
七、block要用什么属性来修饰
1.当block里面会有b类参数要回调回去的时候 属性用copy修饰 将其拷贝到堆里面 这样既是栈释放
掉了 b类指针也在堆中存在 能够成功的回调回去
2.如果语法块仅仅是执行而不再回调回去了 比如操作某个数据库 修改某个单例类的属性 发送某个通知之类的可以用weak来修饰
如果不需要回调就不需要用copy 因为可以优化内存 如果这个类要传入1000Block来执行
而这个类又不会马上释放掉的话 用copy就相当于拷贝了1000个在堆里面
这样就会占用一大部分的内存 如果使用weak将不必要的执行后马上释放掉就可以节省了很多内存
八、事件是如何产生与传递的?
答:当发生触摸事件后 系统会将该事件加入到一个由UIApplication管理的事件队列中 UIApplication会从时间队列中取出最前面的时间 并将时间分布发送下去以便处理 主窗口会在视图层次结构中找到一个最合适的视图来处理触摸时间
触摸时间的传递是从父控件传递到子控件的 如果一个父控件不能接收事件 那么他里面的子控件也不能接收
当一个控件不能接收事件时一般有几种情况
1.不接受用户交互userInteractionEnabled = NO
2.当一个控件隐藏时Hidden = YES
3.当一控件为透明白时
值得注意的是:UIImageView以及它的子控件默认是不能接收触摸事件的
九、事件的响应
用户点击屏幕产生的一个触摸事件 经过一系列的传递过程后 会找到一个最适合的视图来处理事件
找到最合适的视图控件后 就会调用控件的touches方法来作具体的事件处理 touches的默认做法是
将事件顺着响应者链条向上传递 将事件交给上一响应者处理
什么是响应者链条?
由多个响应者对象链接起来的链条
什么是响应者对象?
继承了UIResponder的对象
如何去寻找上一个响应者?
1.如果当前的View是控制器的View 那么控制器就是上一个响应者
2.如果当前的View不是控制器的View 那么他的父控件就是上一个响应者
3.在视图层次结构的最顶级视图 如果不能处理收到的事件或消息 则其将事件或消息传递给window对象也不处理 则其将事件或消息传递给UIApplication对象
5.如果UIApplilcation也不能处理该事件或消息 则将其丢弃
十、系统是如何寻找最合的View
1.先判断自己是否能接收触摸事件
2.在判断触摸事件当前点在不在自己身上
3.如果在自己身上 他会从后往前遍历子控件 遍历出每一个控件后 重启前两步
4.如果没有符合条件的子控件 那么自身就是最合适的View
在寻找最合适View的过程中 系统会调用2个方法
第一方法的作用是:寻找最合适的View 那么什么时候调用呢?-就是当前事件传递给当前的view时就会调用这个方法
第二个方法的作用是:判断触摸点在不在当前的view上 那么什么时候调用呢?-就是在hitTest方法中会自动调用这个方法
注意:point必须得要跟当前view在同一个坐标系
来看hitTest:withEvent:方法四如何实现的呢?
在开发中或多或少会需要一些特殊的点击
比方说:一个按钮被一个半透明的View部分遮挡 需要点击到按钮的时候 按钮始终响应
一个View超出了父视图的范围 需要点击超出范围的View也有响应
十一、如何访问并修改一个类的私有属性
1.有两种方式可以访问私有属性 一种是通过KVC获取 一种是通过runtime访问并修改私有属性
2.创建一个Father类 声明一个私有属性name 并重写description打印name的值 在另外一个类中通
过runtime来获取并修改Father中的属性
担心个别同学之前没有了解过运行时 所以我会把步骤说的详细些:
十二、iOS Extension 是什么?举例几个常用的Extension
1.Extension是扩展 没有分类名字 是一种特殊的分类 类扩展可以扩展属性 成员变量和方法
2.常用的扩展是在.m文件中声明私有属性和方法
十三、如何把一个包含自定义对象的数组序列化到磁盘
*自定义对象只需要实现NSCoding协议即可
遵循两个代理