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

除了"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 分类之外的其他分类中,可以定义存取方法,但是尽量不要定义属性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值