浅谈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;
}

3、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;
}

以上这篇浅谈iOS中几个常用协议 NSCopying/NSMutableCopying就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • HTTP/2 协议用于 iOS 推送提醒服务 (APNS)

    苹果最近更新了他们的推送提醒服务协议,APNS.这个新版本的协议基于HTTP/2和JSON,相比于旧的二进制协议,新的协议有了巨大改进. 新的APNS协议基于HTTP/2: 新的特性和功能: 基于JSON的请求和响应 对于每个通知,如果成功响应,将会返回200标识 - 不用再去猜测通知是否被接收到 响应错误将会以JSON字符的形式返回 消息的长度从2048个字节增加到4096个字节 连接状态可以通过HTTP/2的ping框架来进行检查 支持主题 通用的推送证书 - 开发和生产使用同一个证书即可

  • iOS中NSObject的两种含义:类和协议详解

    前言 协议中<NSobject>是什么意思? 子类继承了父类,子类会遵守父类遵守的协议吗? 会遵守NSObject协议,但是只在头文件中声明,编译器是不会自动生成实例变量的.需要自己处理getter和setter 方法 NS/CF/CG/CA/UI这些前缀分别是什么含义: CF CocoaFundation框架 CG CoreGraphics框架 CA Coreanimatigon框架 UI UIkit框架 下面话不多说了,来一起看看详细的介绍吧 1. 区分:类的NSObject与协议的NSO

  • 浅谈iOS中几个常用协议 NSCopying/NSMutableCopying

    1.几点说明 说到NSCopying和NSMutableCopying协议,不得不说的就是copy和mutableCopy. 如果类想要支持copy操作,则必须实现NSCopying协议,也就是说实现copyWithZone方法; 如果类想要支持mutableCopy操作,则必须实现NSMutableCopying协议,也就是说实现mutableCopyWithZone方法; iOS系统中的一些类已经实现了NSCopying或者NSMutableCopying协议的方法,如果向未实现相应方法的系

  • 浅谈Java中几个常用集合添加元素的效率

    初始化需要进行比较的集合,统一增加10万个元素,获取整个过程的执行时间. 1.List集合增加元素 private static void testList() { List<Integer> list = new ArrayList<Integer>(); long startTime = System.currentTimeMillis(); // 获取开始时间 for (int i = 0; i < 100000; i++) { list.add(i); } long

  • 浅谈iOS中的锁的介绍及使用

    在平时的开发中经常使用到多线程,在使用多线程的过程中,难免会遇到资源竞争的问题,那我们怎么来避免出现这种问题那? 线程安全是什么? 当一个线程访问数据的时候,其他的线程不能对其进行访问,直到该线程访问完毕.简单来讲就是在同一时刻,对同一个数据操作的线程只有一个.只有确保了这样,才能使数据不会被其他线程影响.而线程不安全,则是在同一时刻可以有多个线程对该数据进行访问,从而得不到预期的结果. 比如写文件和读文件,当一个线程在写文件的时候,理论上来说,如果这个时候另一个线程来直接读取的话,那么得到的结

  • 浅谈MySQL中四种常用存储引擎

    MySQL常用的四种引擎的介绍 (1):MyISAM存储引擎: 不支持事务.也不支持外键,优势是访问速度快,对事务完整性没有 要求或者以select,insert为主的应用基本上可以用这个引擎来创建表 支持3种不同的存储格式,分别是:静态表:动态表:压缩表 静态表:表中的字段都是非变长字段,这样每个记录都是固定长度的,优点存储非常迅速,容易缓存,出现故障容易恢复:缺点是占用的空间通常比动态表多(因为存储时会按照列的宽度定义补足空格)ps:在取数据的时候,默认会把字段后面的空格去掉,如果不注意会把

  • 浅谈iOS中三种生成随机数方法

    ios 有如下三种随机数方法: //第一种 srand((unsigned)time(0)); //不加这句每次产生的随机数不变 int i = rand() % 5; //第二种 srandom(time(0)); int i = random() % 5; //第三种 int i = arc4random() % 5 ; 注: ① rand()和random()实际并不是一个真正的伪随机数发生器,在使用之前需要先初始化随机种子,否则每次生成的随机数一样. ② arc4random() 是一个

  • 浅谈IOS中AFNetworking网络请求的get和post步骤

    1.首先通过第三方:CocoaPods下载AFNetworking 1.1.先找到要查找的三方库:pod search + AFNetworking 1.2.出来一堆列表页面,选择三方库最新版本命令,例如: pod 'MBProgressHUD','~>0.8'  (:q 返回) 1.3.创建工程,进入工程: cd + 工程路径 1.4.编辑工程的Podfile文件: vim Podfile 1.5.(platform :iOS, '8.0'
target "工程名" do
po

  • 浅谈iOS开发中static变量的三大作用

    (1)先来介绍它的第一条也是最重要的一条:隐藏 当我们同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性.为理解这句话,我举例来说明.我们要同时编译两个源文件,一个是a.c,另一个是main.c. 下面是a.c的内容 char a = 'A'; // global variable void msg() { printf("Hello\n"); } 下面是main.c的内容 int main(void) { extern char a; // extern v

  • 浅谈python中列表、字符串、字典的常用操作

    列表操作如此下: a = ["haha","xixi","baba"] 增:a.append[gg] a.insert[1,gg] 在下标为1的地方,新增 gg 删:a.remove(haha) 删除列表中从左往右,第一个匹配到的 haha del a.[0] 删除下标为0 对应的值 a.pop(0) 括号里不写内容,默认删除最后一个,写了,就删除对应下标的内容 改:a.[0] = "gg" 查:a[0] a.index(&q

  • 浅谈iOS应用中的相关正则及验证

    1.手机号码的验证正则 正则表达式: ^((13[0-9])|(15[^4,\\D])|(18[0,0-9]))\\d{8}$ 详细解释 解释: •^...$: ^:开始 $:结束 中间为要处理的字串 •(13[0-9]): 以13开头接下来一位为0-9之间的数 13 : 以13开头 [0-9]:分割语法,13后面是0-9之间的数 •| : 或(or), 将前后两个匹配条件进行or运算 • (15[^4\\D]) : 以15开头接下来一位是除4之外的0-9数字 15 : 以15开头 [^4\\D

  • 浅谈Java中常用数据结构的实现类 Collection和Map

    线性表,链表,哈希表是常用的数据结构,在进行Java开发时,JDK已经为我们提供了一系列相应的类来实现基本的数据结构.这些类均在java.util包中.本文试图通过简单的描述,向读者阐述各个类的作用以及如何正确使用这些类. Collection ├List │├LinkedList │├ArrayList │└Vector │ └Stack └Set Map ├Hashtable ├HashMap └WeakHashMap Collection接口 Collection是最基本的集合接口,一个C

随机推荐