一.语法相关
1. _weak
- 默认strong,可选weak。strong下不管成员变量还是property,每次使用指针指向一个对象,等于自动调用retain(), 并对旧对象调用release(),所以设为nil等于release。
只要某个对象被任一strong指针指向,那么它将不会被销毁,否则立即释放,不用等runloop结束。所有strong指针变量不需要在dealloc中手动设为nil,ios会自动处理,debug可以看到全部被置为nil,最先声明的变量最后调用dealloc释放。
官方建议IBOutlet加上__weak,实际上不用加也会自动释放;
优先使用私有成员变量,除非需要公开属性才用property。
避免循环引用,否则手动设置nil释放。
block方法常用声明:@property (copy) void(^MyBlock)(void); 如果超出当前作用域之后仍然继续使用block,那么最好使用copy关键字,拷贝到堆区,防止栈区变量销毁。
创建block匿名函数之前一般需要对self进行weak化,否则造成循环引用
2. typeof
typeof的参数可以是两种形式:表达式或类型。
关键字typeof用于获取表达式的数据类型。只有部分编译器支持,这个特性在linux内核中应用非常广泛,很显然Clang支持这个特性。
局限:typeof构造中的类型名不能包含存储类说明符,如extern或static。不过允许包含类型限定符,如const或volatile。例如,下列代码是无效的,因为它在typeof构造中声明了extern:
typeof(extern int) a;
二. 项目中用到的weakSelf宏及其进化
我们都知道在防止如block的循环引用时,会使用__weak关键字做如下定义:
__ typeof() weakSelf = ;
后来,为了方便,不用每次都要写这样一句固定代码,我们定义了宏:
#define WeakSelf __weak typeof() weakSelf = ;
之后,我们可以比较方便的在需要的地方:
WeakSelf;
[weakSelf doSomething];
再后来,我们发现不止self需要使用weak,可能有部分变量也需要weak,于是我们的宏继续进化,不仅仅只支持self:
#define WeakObj(o) __weak typeof(o) o##Weak = o;
这样,后续对需要使用weak的对象,只要写一句WeakObj(obj) 即可使用objWeak变量了(PS:发现没有,这里生成的变量名其实是objWeak,并不是weakObj,原因见文章末的注1)
再后来,我们发现了一些小技巧,可以让我们的这个宏看起来更原生一些,我们添加了@符号在前面:
#define WeakObj(o) autoreleasepool{} __weak typeof(o) o##Weak = o;
使用上看起来是这样
@WeakObj(obj);
[selfWeak doSomething];
是不是感觉挺高大上的?
这个@只是为了让这个宏定义看起来更像一条指令,并没有其他的作用,不会对实际代码产生什么影响,一个小trick。这里是利用了@autoreleasepool{}这个系统的关键字来实现的,其实还可以利用@try{}@finally{}这个也可以达到相同的效果,比如:
#define WeakObj() @finally{} __weak typeof(o) o##Weak = o;
这部分空的@try或者空的@autoreleasepool会在编译时被优化掉,不必担心性能问题。
还有相应的strong宏,一并晒在这里
#define StrongObj(o) autoreleasepool{} __strong typeof(o) o = o##Weak;
参考:
1. http://stackoverflow.com/questions/34185282/understanding-weakify-macro
2. http://blog.csdn.net/u010124617
3. http://blog.chinaunix.net/uid-28458801-id-4200573.html