iOS中几个常用协议(一)NSCopying/NSMutableCopying)

1、几点说明

说到NSCopying和NSMutableCopying协议,不得不说的就是copy和mutableCopy。

  • 如果类想要支持copy操作,则必须实现NSCopying协议,也就是说实现copyWithZone方法;
  • 如果类想要支持mutableCopy操作,则必须实现NSMutableCopying协议,也就是说实现mutableCopyWithZone方法;
  • iOS系统中的一些类已经实现了NSCopying或者NSMutableCopying协议的方法,如果向未实现相应方法的系统类或者自定义类发送copy或者mutableCopy消息,则会crash。
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Person copyWithZone:]: unrecognized selector sent to instance 0x6080000314c0'
  • 发送copy和mutableCopy消息,均是进行拷贝操作,但是对不可变对象的非容器类、可变对象的非容器类、可变对象的容器类、不可变对象的容器类中复制的方式略有不同;但如下两点是相同的:

  • 发送copy消息,拷贝出来的是不可变对象;

  • 发送mutableCopy消息,拷贝出来的是可变对象;

  • 故如下的操作会导致crash

NSMutableString *test1 = [[NSMutableString alloc]initWithString:@"11111"];
NSMutableString  *test2 = [test1 copy];
[test2 appendString:@"22222"];

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSTaggedPointerString appendString:]: unrecognized selector sent to 

2、系统非容器类

系统提供的非容器类中,如NSString,NSMutableString,有如下特性:

  • 向不可变对象发送copy,进行的是指针拷贝;向不可变对象发送mutalbeCopy消息,进行的是内容拷贝;
NSString *test3 = @"111111";
NSString *test4 = [test3 copy];
NSMutableString *test5 = [test3 mutableCopy];
NSLog(@"test3 is %p, test4 is %p, tast5 is %p",test3,test4,test5);

test3 is 0x10d6bb3a8, test4 is 0x10d6bb3a8, tast5 is 0x600000073e80
  • 向可变对象发送copy和mutableCopy消息,均是深拷贝,也就是说内容拷贝;
NSMutableString *test11 = [[NSMutableString alloc]initWithString:@"444444"];
NSString  *test12 = [test11 copy];    
NSMutableString *test13 = [test11 mutableCopy];    
NSLog(@"test11 is %p, test12 is %p, tast13 is %p",test11,test12,test13);
    
test11 is 0x600000073e00, test12 is 0xa003434343434346, tast13 is 0x600000073dc0

3、系统容器类

系统提供的容器类中,如NSArray,NSDictionary,有如下特性:

  • 不可变对象copy,是浅拷贝,也就是说指针复制;发送mutableCopy,是深复制,也就是说内容复制;
NSArray *array = [NSArray arrayWithObjects:@"1", nil];
NSArray *copyArray = [array copy];
NSMutableArray *mutableCopyArray = [array mutableCopy];
NSLog(@"array is %p,  copyArray is %p,  mutableCopyArray is %p", array, copyArray, mutableCopyArray);

array is 0x60800001e580,  copyArray is 0x60800001e580,  mutableCopyArray is 0x608000046ea0
  • 可变对象copy和mutableCopy均是单层深拷贝,也就是说单层的内容拷贝;
NSMutableArray *element = [NSMutableArray arrayWithObject:@1];
NSMutableArray *array = [NSMutableArray arrayWithObject:element];
NSArray *copyArray = [array copy];
NSMutableArray *mutableCopyArray = [array mutableCopy];

NSLog(@"array is %p,  copyArray is %p,  mutableCopyArray is %p", array, copyArray, mutableCopyArray);

[mutableCopyArray[0] addObject:@2];

NSLog(@"element is %@,  array is %@,  copyArray is %@,  mutableCopyArray is %@", element,array,copyArray, mutableCopyArray);
    
2017-02-22 11:53:25.286 test[91520:3915695] array is 0x600000057670,  copyArray is 0x600000000bc0,  mutableCopyArray is 0x6080000582a0
2017-02-22 11:53:25.287 test[91520:3915695] element is (
1,
2
),  array is (
    (
    1,
    2
)
),  copyArray is (
    (
    1,
    2
)
),  mutableCopyArray is (
    (
    1,
    2
)
)
    

4、自定义的类

重要说明:
1、所以的代码设计均是针对业务需求。
2、对于自定义的类,决定能否向对象发送copy和mutableCopy消息也是如此;

1、@property 声明中用 copy 修饰

不得不说下copy和strong在复制时候的区别,此处不讲引用计数的问题。
copy:拷贝一份不可变副本赋值给属性;所以当原对象值变化时,属性值不会变化;
strong:有可能指向一个可变对象,如果这个可变对象在外部被修改了,那么会影响该属性;

@interface Person : NSObject 
@property (nonatomic, copy) NSString *familyname;
@property (nonatomic, strong) NSString *nickname;
@end

Person *p1 = [[Person alloc]init];
    
NSMutableString *familyname = [[NSMutableString alloc]initWithString:@"张三"];
p1.familyname = familyname;
[familyname appendString:@"峰"];
    
NSLog(@"p1.familyname is %@",p1.familyname);
    
NSMutableString *nickname = [[NSMutableString alloc]initWithString:@"二狗"];
p1.nickname = nickname;
[nickname appendString:@"蛋儿"];
    
NSLog(@"p1.nickname is %@", p1.nickname);

2017-02-22 13:53:58.979 test[98299:3978965] p1.familyname is 张三
2017-02-22 13:53:58.979 test[98299:3978965] p1.nickname is 二狗蛋儿

2、类的对象的copy

此处唯一需要说明的一点就是注意类的继承。
这篇文章有非常清晰详细的说明,此处只照搬下结论:

  • 1 类直接继承自NSObject,无需调用[super copyWithZone:zone]
  • 2 父类实现了copy协议,子类也实现了copy协议,子类需要调用[super copyWithZone:zone]
  • 3 父类没有实现copy协议,子类实现了copy协议,子类无需调用[super copyWithZone:zone]
  • 4、copyWithZone方法中要调用[[[self class] alloc] init]来分配内存

5、NSCopying

  • NSCopying是对象拷贝的协议。
  • 类的对象如果支持拷贝,该类应遵守并实现NSCopying协议。
  • NSCopying协议中的方法只有一个,如下:
- (id)copyWithZone:(NSZone *)zone {    
    Person *model = [[[self class] allocWithZone:zone] init];
    model.firstName = self.firstName;
    model.lastName  = self.lastName;
    //未公开的成员
    model->_nickName = _nickName;
    return model;
}

2、NSMutableCopying

当自定义的类有一个属性是可变对象时,对此属性复制时要执行mutableCopyWithZone操作。

- (id)copyWithZone:(NSZone *)zone {
    AFHTTPRequestSerializer *serializer = [[[self class] allocWithZone:zone] init];
    serializer.mutableHTTPRequestHeaders = [self.mutableHTTPRequestHeaders mutableCopyWithZone:zone];
    serializer.queryStringSerializationStyle = self.queryStringSerializationStyle;
    serializer.queryStringSerialization = self.queryStringSerialization;
    
    return serializer;
}

5、参考文章:

http://www.jianshu.com/p/cfdbd4d7f162
http://blog.csdn.net/qq_18425655/article/details/51325921
https://www.oschina.net/question/2330001_2181415
https://www.zybuluo.com/MicroCai/note/50592

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,825评论 4 377
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,887评论 2 308
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,425评论 0 255
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,801评论 0 224
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,252评论 3 299
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,089评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,216评论 2 322
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 31,005评论 0 215
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,747评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,883评论 2 255
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,354评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,694评论 3 265
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,406评论 3 246
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,222评论 0 9
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,996评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,242评论 2 287
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 36,017评论 2 281

推荐阅读更多精彩内容