36、不要使用retainCount
对象的保留计数看似有用,实则不然,因为任何给定时间点上的“绝对保留计数”(absolute retain count)都无法反应对象生命期的全貌,如未考虑系统的自动释放池的操作等等。
引用ARC之后,retainCount方法就正式废止了,在ARC下调用该方法会导致编译器报错。
37block的理解
块 | |
void* | isa |
int | flags |
int | reserved |
void(*)(void*,...) | invoke |
struct* | descriptor |
捕获到的变量 |
块描述符 | |
unsigned long int | reserved |
unsigned long int | size |
void(*)(void*,void*) | copy |
void(*)(void*,void*) | dispose |
块是C、C++、Objective-C的词法闭包。
块可接受参数,也可返回值。
块可以分配在栈或堆上,也可以是全局的。分配在栈上的块可拷贝(copy)到堆里,这样的话,就和标准的Objective-C对象一样,具备引用计数了。
38、可以为block类型创建typedef
以typedef重新定义块类型,可令块变量用起来更简单。
定义新类型时应遵从现有的命名规范,勿使其名称与别的类型相冲突。
不妨为同一个块签名定义多个类型别名。如果要重构的代码使用了块类型的某个别名,那么只需要修改相应的typedef中的块签名即可,无须改动其他typedef。如:
typedef void(^ACAccountStoreSaveCompletionHandler)(BOOL success, NSError *error);
typedef void(^ACAccountStoreRequestAccessCompletionHandler)(BOOL granted, NSError *error);
39、用handle块降低代码分散程度
创建对象时,可以使用内联的handler块将相关业务逻辑一并声明。
在有多个实例需要监控时,如果采用委托模式,那么经常需要根据传入的对象来切换,而采用handler块来实现,则可以直接将块与相关对象放在一起。
设计API时如果用到了handler块,那么可以增加一个参数,使调用者可通过此参数来决定应该把块安排在哪个队列上执行。如下:
-(id)addObserverForName:(NSString *)name object:(id)object queue:(NSOperationQueue*)queue usingBlock:(void (^)(NSNotification*))block;
40、block块引用其所属对象时不要出现保留环
如果块所属的对象直接或者间接保留了块本身,那么就得当心保留环的问题。
一定要找个适当的时机解除保留环,而不能把责任推给API的调用者。如下(_completionHandler为block块成员):
-(void)p_requestCompleted{
if (_completionHandler){
_completionHandler(_downloadedData);
}
self.completionHandler = nil;
}