编写高质量OC代码52建议总结:26.不要在分类中设置属性

来源:互联网 发布:珠海网络电视 编辑:程序博客网 时间:2024/05/16 05:57
除了"class-continuation"分类之外,其他分类都无法向类中新增实例变量。因此,无法合成实现属性所需的实例变量。

 例如:专门设计一个处理交友事物的类,其中所有的方法都与操作朋友列表有关。

#import "LYKPerson.h"@interface LYKPerson ()@property (nonatomic, copy, readonly) NSString *firstName;@property (nonatomic, copy, readonly) NSString *lastName;-(id)initWithFirstName:(NSString *)firstName andLastName:(NSString *)lastName;@end@implementation LYKPerson-(id)initWithFirstName:(NSString *)firstName andLastName:(NSString *)lastName{    return nil;}@end@interface LYKPerson (Friendship)@property (nonatomic, strong) NSArray *friends;-(BOOL)isFriendsWith:(LYKPerson *)person;@end//Property 'friends' requires method 'setFriends:' to be defined - use @dynamic or provide a method implementation in this category//Property 'friends' requires method 'friends' to be defined - use @dynamic or provide a method implementation in this category@implementation LYKPerson (Friendship)-(BOOL)isFriendsWith:(LYKPerson *)person{    return YES;}@end
 如果将分类也放入Friendship,编译这段代码时,编译器报警告。
 意思是:此分类无法合成与friends属性相关的实例变量,开发者需要在分类中为该属性实现存取方法。此时可以将存取方法声明为@dynamic,等运行时再提供方法。
 
 关联对象也能够解决此问题

static const char *key = "kty";@implementation LYKPerson (Friendship)-(BOOL)isFriendsWith:(LYKPerson *)person{    return YES;}-(NSArray *)friends{    return objc_getAssociatedObject(self, key);}-(void)setFriends:(NSArray *)friends{    objc_setAssociatedObject(self,                             key,                             friends,                             OBJC_ASSOCIATION_RETAIN);}@end

这样做,需要把相似的代码写好多遍,而且在内存管理语义上容易出错,这种方法并不推荐。
 还可以通过可变数组来实现friends属性所对应的实例变量,就得在设置方法中将传入的数组参数拷贝为可变版本。这种方法也容易出错。
 
 应该把所有属性都定义在主接口中,类所封装的全部数据都应该定义在主接口中。
 
 总结:
 1.把封装数据所用的全部属性都定义在主接口中
 2.在 class-continuation 分类之外的其他分类中,可以定义存取方法,但是尽量不要定义属性。

0 0
原创粉丝点击