如何让自己的类用 copy 修饰符?

如何让自己的类用 copy 修饰符?

 NSArray *tempArray = @[@"1",@"2"];
NSMutableArray *mutableCopyMuArray = [tempArray mutableCopy];

// tempArray==0x600002649ce  mutableCopyMuArray==0x600002649ce0
// 深copy tempArray 和 mutableCopyMuArray是完全不同的变量
NSLog(@"tempArray==%p,mutableCopyMuArray==%p",tempArray,mutableCopyMuArray);


 WQUser *user = [[WQUser alloc] initWithName:@"lbj" age:35];
/*
 WQUser自己新建的类不具备copy功能,程序会crash
 声明NSCopying并且实现协议方法后,新建的类会具备copy功能
 user==0x600002f7b400,copyUser==0x600002f7b3e0,copy出来完全不同的变量
 */

WQUser *copyUser = [user copy];

NSLog(@"user==%p,copyUser==%p",user,copyUser);

若想令自己所写的对象具有拷贝功能,则需实现 NSCopying 协议。如果自定义的对象分为可变版本与不可变版本,那么就要同时实现 NSCopying 与 NSMutableCopying 协议。

具体步骤:

  1. 需声明该类遵从 NSCopying 协议
  2. 实现 NSCopying 协议。该协议只有一个方法:
#import "WQUser.h"
@interface WQUser ()<NSCopying>

@property (nonatomic, readonly, copy) NSString *name;
@property (nonatomic, readonly, assign) NSUInteger age;
@property (nonatomic, readwrite, strong) NSMutableSet *friends;

@end

@implementation WQUser

- (instancetype)initWithName:(NSString *)name
                 age:(NSUInteger)age {
if (self = [super init]) {
_name = [name copy];
_age = age;
_friends = [[NSMutableSet alloc] init];
}
return self;
}    

#pragma mark - NSCopying
- (id)copyWithZone:(nullable NSZone *)zone {

WQUser *copy = [[[self class] allocWithZone:zone] initWithName:_name age:_age];
copy.friends = [[NSMutableSet alloc] initWithSet:_friends copyItems:true];

return copy;
}    
@end    

如何重写带 copy 关键字的 setter?

/*
 不要在 setter 里进行像 if(_obj != newObj) 这样的判断
 什么情况会在 copy setter 里做 if 判断? 例如,车速可能就    有最高速的限制,车速也不可能出现负值,如果车子的最高速为    300,则 setter 的方法就要改写成这样:
     - (void)setSpeed:(int)_speed{
 if(_speed < 0) speed = 0;
 if(_speed > 300) speed = 300;
 _speed = speed;
 }
 */
- (void)setName:(NSString *)name {
//[_name release]; // MRC
_name = [name copy];
}