首页 > 代码库 > iOS 8:Mutable属性返回Immutable值
iOS 8:Mutable属性返回Immutable值
标题有些绕。举个例子:在头文件中声明一个不可变数组,如- (NSArray *)images;然后在匿名类延展中定义一个可变的属性变量,如@property (nonatomic, strong) NSMutableArray *images; // for UIImageView。如下所示:
@interface StarImageView : UIView- (NSArray *)images;- (void)addImageWithName:(NSString *)imageName;@end@interface StarImageView ()@property (nonatomic, strong) NSMutableArray *images; // for UIImageView@end
现在问题来了,这样做不会引起冲突吗?毕竟,声明一个属性变量会自动声明getter和setter方法,自动声明的getter方法的返回值显然是NSMutableArray *,而非NSArray *。
答案是不会。因为属性类型(NSMutableArray)是头文件所用类型(NSArray)的子类,所以它能正常运行。这意味着可以在类里面使用这个可变数组,但是我们希望通过API公开的是一个看似不可变的NSArray数组。所有使用这段代码的人都应该对这个类有提供的API有一致的理解(约定)。如果深入源码,发现这个属性实际返回的是一个NSMutableArray,继而跳过API直接使用它的话,就会破坏这种约定,那就不是类设计者的问题了。
另一个问题是,如果在类内部使用此属性。一般建议在类内部也使用属性访问,而不是直接访问底层的实例变量(米高注:这点可能和《Effective Objective-C》有出入,但是,根据一些资料,如《iOS 7编程实战》,可知苹果对自动生成的getter及setter有优化,另外,直接访问底层的实例变量与访问getter及setter在大部分场合所带来的性能损耗是微不足道的,反而,直接访问在某些场合会让getter中设置的内存一致等处理失效,这样反而危害更大。)这样做的原因很巧妙:虽然在类扩展中将属性变量定义为NSMutableArray类型,但编译器会在处理self.images时发现头文件的@interface中声明的是一个不可变的NSArray!这种变相的解决办法与平常的编码风格不同,不过能正常使用即可。
参考文献:
Jack Nutting 等著, 周庆成 等译. 精通iOS开发(第6版). 北京, 人民邮电出版社. 211 ~ 213页
iOS 8:Mutable属性返回Immutable值