1.什么情况使用 weak 关键字?相比 assign 有什么不同?
在 ARC 中,在有可能出现循环引用的时候,往往要通过让其中一端使用 weak 来解决,比如: delegate 代理属性
自身已经对它进行一次强引用,没有必要再强引用一次,此时也会使用 weak,自定义 IBOutlet 控件属性一般也使用 weak;当然,也可以使用strong。在下文也有论述:《IBOutlet连出来的视图属性为什么可以被设置成weak?》
不同点:
weak 修饰符表明该属性定义了一种“非拥有关系” (nonowning relationship)。在为这种属性设置新值时,设置方法既不保留新值,也不释放旧值。此行为与 assign 类似,不同之处在于,在 weak 属性所指的对象遭到销毁、释放时,该属性值也会清空(nil out)。而 assign 的“设置方法”只会执行针对“纯量类型/基本数据类型” (scalar type,例如 CGFloat 或 NSInteger 等)的简单赋值操作。
assign 可以用非 OC 对象,而 weak 必须用于 OC 对象
2.怎么用 copy 关键字?
NSString、NSArray、NSDictionary 等等经常使用copy关键字,是因为他们有对应的可变类型:NSMutableString、NSMutableArray、NSMutableDictionary;
block 也经常使用 copy 关键字(也可以使用strong ,内部实现是,还是使用copy)。
block 使用 copy 是从 MRC 遗留下来的“传统”,在 MRC 中,方法内部的 block 是在栈区的,使用 copy 可以把它放到堆区.
在 ARC 中写不写都行:
在 ARC 环境下,编译器会根据情況自动将栈上的 block 复制到堆上,比如以下情况:
block 作为函数返回值时
将 block 赋值给 __strong 指针时(property 的 copy 属性对应的是这一条)
block 作为 Cocoa API 中方法名含有 using Block 的方法参数时
block 作为 GCD API 的方法参数时
其中, block 的 property 设置为 copy, 对应的是这一条:将 block 赋值给 __strong 指针时。
换句话说:
对于 block 使用 copy 还是 strong 效果是一样的,但写上 copy 也无伤大雅,还能时刻提醒我们:编译器自动对 block 进行了 copy 操作。如果不写 copy ,该类的调用者有可能会忘记或者根本不知道“编译器会自动对 block 进行了 copy 操作”,他们有可能会在调用之前自行拷贝属性值。这种操作多余而低效。你也许会感觉我这种做法有些怪异,不需要写还依然写。如果你这样想,其实是你“日用而不知”,你平时开发中是经常在用我说的这种做法的,比如下面的属性不写copy也行,但是你会选择写还是不写呢?