热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

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

下面小编就为大家分享一篇浅谈iOS中几个常用协议NSCopyingNSMutableCopying,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

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就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。


推荐阅读
  • 在计算机技术的学习道路上,51CTO学院以其专业性和专注度给我留下了深刻印象。从2012年接触计算机到2014年开始系统学习网络技术和安全领域,51CTO学院始终是我信赖的学习平台。 ... [详细]
  • 本文详细介绍了 Dockerfile 的编写方法及其在网络配置中的应用,涵盖基础指令、镜像构建与发布流程,并深入探讨了 Docker 的默认网络、容器互联及自定义网络的实现。 ... [详细]
  • 本文详细介绍了如何使用Spring Boot进行高效开发,涵盖了配置、实例化容器以及核心注解的使用方法。 ... [详细]
  • 本文详细介绍了W3C标准盒模型和IE传统盒模型的区别,探讨了CSS3中box-sizing属性的使用方法及其在布局中的重要性。通过实例分析,帮助读者更好地理解和应用这一关键概念。 ... [详细]
  • 题库来源:安全生产模拟考试一点通公众号小程序G3锅炉水处理报名考试是安全生产模拟考试一点通生成的,G3锅炉水处理证模拟考试题库是根据G3锅炉水处理最新 ... [详细]
  • 本文详细探讨了Netty中Future及其子类的设计与实现,包括其在并发编程中的作用和具体应用场景。我们将介绍Future的继承体系、关键方法的实现细节,并讨论如何通过监听器和回调机制来处理异步任务的结果。 ... [详细]
  • 2023年京东Android面试真题解析与经验分享
    本文由一位拥有6年Android开发经验的工程师撰写,详细解析了京东面试中常见的技术问题。涵盖引用传递、Handler机制、ListView优化、多线程控制及ANR处理等核心知识点。 ... [详细]
  • 本文介绍如何在 Unity 的 XML 配置文件中,将参数传递给自定义生命周期管理器的构造函数。我们将详细探讨 CustomLifetimeManager 类的实现及其配置方法。 ... [详细]
  • Ralph的Kubernetes进阶之旅:集群架构与对象解析
    本文深入探讨了Kubernetes集群的架构和核心对象,详细介绍了Pod、Service、Volume等基本组件,以及更高层次的抽象如Deployment、StatefulSet等,帮助读者全面理解Kubernetes的工作原理。 ... [详细]
  • Hadoop入门与核心组件详解
    本文详细介绍了Hadoop的基础知识及其核心组件,包括HDFS、MapReduce和YARN。通过本文,读者可以全面了解Hadoop的生态系统及应用场景。 ... [详细]
  • 本文详细探讨了Java中StringBuffer类在不同情况下的扩容规则,包括空参构造、带初始字符串和指定初始容量的构造方法。通过实例代码和理论分析,帮助读者更好地理解StringBuffer的内部工作原理。 ... [详细]
  • 本文探讨了领域驱动设计(DDD)的核心概念、应用场景及其实现方式,详细介绍了其在企业级软件开发中的优势和挑战。通过对比事务脚本与领域模型,展示了DDD如何提升系统的可维护性和扩展性。 ... [详细]
  • 深入了解 Windows 窗体中的 SplitContainer 控件
    SplitContainer 控件是 Windows 窗体中的一种复合控件,由两个可调整大小的面板和一个可移动的拆分条组成。本文将详细介绍其功能、属性以及如何通过编程方式创建复杂的用户界面。 ... [详细]
  • 实体映射最强工具类:MapStruct真香 ... [详细]
  • 深入解析 Apache Shiro 安全框架架构
    本文详细介绍了 Apache Shiro,一个强大且灵活的开源安全框架。Shiro 专注于简化身份验证、授权、会话管理和加密等复杂的安全操作,使开发者能够更轻松地保护应用程序。其核心目标是提供易于使用和理解的API,同时确保高度的安全性和灵活性。 ... [详细]
author-avatar
谭宏景
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有