Block的本质是什么?
- block本质上也是一个
OC对象,它内部也有个isa指针- block是
封装了函数调用以及函数调用环境的OC对象
循环引用的几种场景
delegate循环引用如果delegate使用strong修饰容易引起循环引用
block循环引用block和self的相互持有会造成循环引用
NSTimer循环引用timer和self的相互引用造成循环引用 在删除对象之前,需要调用timer的invalidate方法
NSMutableArray加入self造成循环引用@interface SomeObj : NSObject @property (nonatomic, strong) NSMutableArray *array; @end [_array addObject:self];
使用类别添加属性比如:有一个类A,给A动态添加属性p。如果p中再引用类A,容易造成循环引用
delegate属性为什么要用weak修饰?
- 如果用
strong修饰,会对监听代理的对象造成强引用,从而对该对象的生命周期产生影响。strong:修饰对象是对该对象进行强引用,外界不能销毁该对象,会导致循环引用(Retain Cycles)weak:修饰对象只是指明该对象,并不负责持有这个对象,对象的销毁是由外部控制的。
为什么__weak 可以解决循环引用?
__weak 声明了一个可以自动 nil 化的弱引用,声明而不持有对象。 self强持有block,block里又强持有self,造成循环引用,__weak声明弱引用对象 __weak只能在ARC模式下使用,也只能修饰对象(如NSString),不能修饰基本数据类型(如int)。
初始化一个weak对象时,runtime会调用一个
objc_initWeak函数,初始化一个新的weak指针指向该对象的地址在objc_initWeak函数中会继续调用
objc_storeWeak函数,在这个过程是用来更新weak指针的指向,同时创建对应的弱引用表WeakTable在对象释放时,会调用
clearDeallocating函数,这个函数会根据对象地址获取所有weak指针数组,然后遍历这个数组置为nil。最后把该条对象的记录从weak表中删除。weak指针指向对象,
不会让对象的引用计数增加,所以block内部就不会持有self对象,破解循环引用。
为什么__Block也可以解决循环引用?
- 因为通过__block的修饰,这时候Block在编译的过程中就会获取外部变量的指针,通过指针来修改变量。
- __block的作用就是将变量复制到堆上去,自己管理生命周期!
- 加了__block关键字之后,会将原本存储在栈区的指针,放到了堆中,而不是复制了一个副本到堆中,所以(block内部)和(结束)指针的地址是相同的且都存在于堆中。
block的变量捕获
block的属性修饰词为什么是copy?使用block有哪些使用注意?
Block 引用了普通外部变量,都是创建在栈区的;对于分配在栈区的对象,我们很容易会在释放之后继续调用,导致程序奔溃,所以我们使用的时候需要将栈区的对象移到堆区,来延长该对象的生命周期。
为什么__block可以修改局部变量
- 相当于加了个标识位,遇到__block就把内存由栈区放在推区。
- 对于__block修饰的局部变量,Block捕获时,记录了该变量的地址。所以后续该变量的值改变了,block调用时,通过地址获取到的值仍然是最新的值。
- __block将局部变量内存的值传递到block内部
block有哪些类型,区别是什么?
| block类型 | 执行copy操作后的效果 |
|---|---|
全局block(NSGlobalBlock) | 什么也不做,不会产生新的block |
栈block(NSStackBlock) | 复制一份栈block到堆区 |
堆block(NSMallocBlock) | 仅仅是block的引用计数加1,不会产生新的block |
Block和Protocol的区别?
- 代理和block的共同特性是
回调机制,不同的是,代理的方法比较多,比较分散,公共接口,方法较多也选择用delegate进行解耦- 使用
block的代码比较集中统一,异步和简单的回调用block更好
Block是为了解决什么问题而使用的?
- block为了
多线程之间调度产生的;- block
也是一个OC对象,可以当参数传递,使用方便简单,灵活,很少的代码就可以实现代码回调.比协议省很多代码
isEquel和hash的关系?
isEquel 用于比较2个对象是否相等, 与==(地址比较)不一样, 可以重写isEquel方法,来进行2个对象的比较hash 是一个类方法,任何类都可以调用这个方法,返回的结果是一个NSInteger值(如果两个对象相等,那么他们的hash值一定相等,但是,如果两个对象的哈希值相等是不能一定推出来这两个对象是相等的)
isEquel 和 isEquelToString
- isEquel 比较的是
2个NSObject的方法- isEquelToString是比较
2个字符串值是否相等- isEquel 首先比较2个对象地址,如果相同就返回YES,如果不同,就比较对象类型,以及属性的值,一般重写 isEquel 来比较2个对象
容错处理你们一般是注意哪些?
字典
数组;
野指针;
NSNull
项目开始容错处理没做?如何防止拦截潜在的崩溃?
例:
1、
category给类添加方法用来替换掉原本存在潜在崩溃的方法。2、利用runtime
方法交换技术,将系统方法替换成类添加的新方法。3、利用
异常的捕获来防止程序的崩溃,并且进行相应的处理。4、使用
@try__Catch__方法进行拦截总结:
1、不要过分相信服务器返回的数据会永远的正确。
2、在对数据处理上,要进行容错处理,进行相应判断之后再处理数据,这是一个良好的编程习惯。
函数指针和 Block区别
相同点:
- 二者都可以看成是一个
代码片段。- 函数指针类型和 Block 类型
都可以作为变量和函数参数的类型不同点:
- 函数指针只
能指向预先定义好的函数代码块,函数地址是在编译链接时就已经确定好的。从内存的角度看,函数指针只不过是指向代码区的一段可执行代码- block 本质是
OC对象,是 NSObject的子类,是程序运行过程中在栈内存动态创建的对象,可以向其发送copy消息将block对象拷贝到堆内存,以延长其生命周期。
__weak 和 _Unsafe_Unretain 的区别?
__weak修饰的指针变量,在指向的内存地址销毁后,会在Runtime的机制下,在离开作用域的时候会将指针赋值null,自动置为nil。
_Unsafe_Unretain不会置为nil,在对象离开作用域的时候就会释放,容易出现悬垂指针,发生崩溃。但是_Unsafe_Unretain比__weak效率高。
__strong在Block内部中的使用
防止self被提前释放,暂时持有对象,出了作用域就会释放该对象。
__weak修饰的对象被Block引用,不会影响对象的释放,而__strong在Block内部修饰的对象,会保证,在使用这个对象在作用域内,这个对象都不会被释放,出了作用域,引用计数就会-1,且__strong主要是用在多线程运用中,如果只使用单线程,只需要使用__weak即可。