(0087)iOS开发之NSString属性为什么要用copy来修饰?

2023-12-03 20:32

本文主要是介绍(0087)iOS开发之NSString属性为什么要用copy来修饰?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

这个问题既是一个面试题,也是开发中经常遇到的问题,NSString 属性到底用copy 还是 strong ?其实如果明白的两者的区别也就不会疑惑了,其实都可以,只是如果你不明白两者的实质的区别,有可能会出现难以发现的异常。但是我们遇到的又很少所有经常用哪个都行,但是不知道有何区别,在此我实际验证一下。记录这个经常模糊不清的问题。

 

1.快速搭建一个demo

- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view, typically from a nib.NSLog(@"\n");// 验证不可变对象NSString[self test];// 验证可变对象NSMutableString// [self test22];// 如果用NSString赋值的话strong和copy(此刻是浅拷贝)是没有区别的// 如果用NSMutableString赋值的话strong没有只是增加了str1的计数器,并没有开辟新的内存// copy的话开辟了新的内存,对string的内容进行修改的话,strong的字符串内容改变了,而copy的并没有改变// 如果需要改变的话可以用strong,如果不需要改变的话用copy// 所以属性指向可变对象时应注意;
}
- (void)test{NSString *string = [NSString stringWithFormat:@"测试文字"];//注释1self.strongStr = string;self.copyssStr = string;NSLog(@"String:%@   strongStr:%@   copyssStr:%@",string,self.strongStr,self.copyssStr);NSLog(@"String   : %p, %p", string, &string);NSLog(@"Strong属性: %p, %p",_strongStr, &_strongStr);NSLog(@"Copy  属性: %p, %p",_copyssStr, &_copyssStr);NSLog(@"\n");string = @"我变了,你没变";NSLog(@"我变 String:%@   strongStr:%@   copyssStr:%@",string,self.strongStr,self.copyssStr);NSLog(@"我变 String   : %p, %p", string, &string);NSLog(@"我变 Strong属性: %p, %p",_strongStr, &_strongStr);NSLog(@"我变 Copy  属性: %p, %p",_copyssStr, &_copyssStr);// NSString总结:用NSString赋值的话strong和copy(此刻是浅拷贝)是没有区别的;从新赋值,相当于指向了新的一个对象,string指向变了,而strong和copy指针(此刻是浅拷贝// 还是指向的原来的对象,所以说不变。// 所以不可变对象的copy 和strong 与可变对象的copy 一样效果,赋值后copy 和 strong 指针指向的值都不变;/*1. 当原字符串是NSMutableString时,Strong属性只是增加了原字符串的引用计数,而Copy属性则是对原字符串做了次深拷贝,产生一个新的对象,且Copy属性对象指向这个新的对象,且这个Copy属性对象的类型始终是NSString,而不是NSMutableString,因此其是不可变的。2. 这里还有一个性能问题,即在原字符串是NSMutableString,Strong是单纯的增加对象的引用计数,而Copy操作是执行了一次深拷贝,所以性能上会有所差异(虽然不大)。如果原字符串是NSString时,则没有这个问题。所以,在声明NSString属性时,到底是选择strong还是copy,可以根据实际情况来定。不过,一般我们将对象声明为NSString时,都不希望它改变,所以大多数情况下,我们建议用copy,以免因可变字符串的修改导致的一些非预期问题。*/
}
- (void)test22{//NSMutableString *string = [NSMutableString stringWithFormat:@"测试文字"];self.strongStr = string;self.copyssStr = string;NSLog(@"String:%@   strongStr:%@   copyssStr:%@",string,self.strongStr,self.copyssStr);NSLog(@"String 地址: %p, %p", string, &string);NSLog(@"Strong 地址: %p, %p",_strongStr, &_strongStr);NSLog(@"Copy   地址: %p, %p",_copyssStr, &_copyssStr);NSLog(@"\n");[string appendString:@"我变了,你没变"];NSLog(@"append 后 String:%@   strongStr:%@   copyssStr:%@",string,self.strongStr,self.copyssStr);NSLog(@"append 后 String 地址: %p, %p", string, &string);NSLog(@"append 后 Strong 地址: %p, %p",_strongStr, &_strongStr);NSLog(@"append 后 Copy   地址: %p, %p",_copyssStr, &_copyssStr);NSLog(@"\n");// NSMutableString总结:// 如果string 的指针不变,内存地址不变,值变化,则strongStr 的值跟着变化,指针不变,地址不变;而copyssStr 则不会任何变化;string = [NSMutableString stringWithFormat:@"ccvcc"];NSLog(@"Mutable 后 String:%@   strongStr:%@   copyssStr:%@",string,self.strongStr,self.copyssStr);NSLog(@"Mutable 后 String 地址: %p, %p", string, &string);NSLog(@"Mutable 后 Strong 地址: %p, %p",_strongStr, &_strongStr);NSLog(@"Mutable 后 Copy   地址: %p, %p",_copyssStr, &_copyssStr);// 总结:Mutable 相当于重新alloc一个对象, string 指针的指向变了,指向了新的对象的地址,strongStr 指针不变,指向的还是原来对象的地址,地址不变;而copyssStr已经去string没有关系,则不会任何变化;// 这里我想验证下strongStr 指向的是原来的还是新的对象的[self performSelector:@selector(shows) withObject:nil afterDelay:10];
}
- (void)shows {NSLog(@"shows 后 strongStr:%@   copyssStr:%@",self.strongStr,self.copyssStr);
}

上面代码中有自己对比得出的结论,推出多用copy 是因为我们使用属性一般是全局的,不期望 *string被改变时,也改变了copy 属性的值。我们希望的是self.copyssStr = @"";来改变

参考:https://www.jianshu.com/p/8bbe01e53114

:https://blog.csdn.net/itianyi/article/details/9018567

:https://blog.csdn.net/summer_csdn123/article/details/52190879

:https://www.jianshu.com/p/b3873ac9259b

这篇关于(0087)iOS开发之NSString属性为什么要用copy来修饰?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/450782

相关文章

Python38个游戏开发库整理汇总

《Python38个游戏开发库整理汇总》文章介绍了多种Python游戏开发库,涵盖2D/3D游戏开发、多人游戏框架及视觉小说引擎,适合不同需求的开发者入门,强调跨平台支持与易用性,并鼓励读者交流反馈以... 目录PyGameCocos2dPySoyPyOgrepygletPanda3DBlenderFife

使用Python开发一个Ditto剪贴板数据导出工具

《使用Python开发一个Ditto剪贴板数据导出工具》在日常工作中,我们经常需要处理大量的剪贴板数据,下面将介绍如何使用Python的wxPython库开发一个图形化工具,实现从Ditto数据库中读... 目录前言运行结果项目需求分析技术选型核心功能实现1. Ditto数据库结构分析2. 数据库自动定位3

Django开发时如何避免频繁发送短信验证码(python图文代码)

《Django开发时如何避免频繁发送短信验证码(python图文代码)》Django开发时,为防止频繁发送验证码,后端需用Redis限制请求频率,结合管道技术提升效率,通过生产者消费者模式解耦业务逻辑... 目录避免频繁发送 验证码1. www.chinasem.cn避免频繁发送 验证码逻辑分析2. 避免频繁

Spring Boot集成/输出/日志级别控制/持久化开发实践

《SpringBoot集成/输出/日志级别控制/持久化开发实践》SpringBoot默认集成Logback,支持灵活日志级别配置(INFO/DEBUG等),输出包含时间戳、级别、类名等信息,并可通过... 目录一、日志概述1.1、Spring Boot日志简介1.2、日志框架与默认配置1.3、日志的核心作用

PyQt5 GUI 开发的基础知识

《PyQt5GUI开发的基础知识》Qt是一个跨平台的C++图形用户界面开发框架,支持GUI和非GUI程序开发,本文介绍了使用PyQt5进行界面开发的基础知识,包括创建简单窗口、常用控件、窗口属性设... 目录简介第一个PyQt程序最常用的三个功能模块控件QPushButton(按钮)控件QLable(纯文本

spring中的@MapperScan注解属性解析

《spring中的@MapperScan注解属性解析》@MapperScan是Spring集成MyBatis时自动扫描Mapper接口的注解,简化配置并支持多数据源,通过属性控制扫描路径和过滤条件,利... 目录一、核心功能与作用二、注解属性解析三、底层实现原理四、使用场景与最佳实践五、注意事项与常见问题六

基于Python开发一个图像水印批量添加工具

《基于Python开发一个图像水印批量添加工具》在当今数字化内容爆炸式增长的时代,图像版权保护已成为创作者和企业的核心需求,本方案将详细介绍一个基于PythonPIL库的工业级图像水印解决方案,有需要... 目录一、系统架构设计1.1 整体处理流程1.2 类结构设计(扩展版本)二、核心算法深入解析2.1 自

Linux线程之线程的创建、属性、回收、退出、取消方式

《Linux线程之线程的创建、属性、回收、退出、取消方式》文章总结了线程管理核心知识:线程号唯一、创建方式、属性设置(如分离状态与栈大小)、回收机制(join/detach)、退出方法(返回/pthr... 目录1. 线程号2. 线程的创建3. 线程属性4. 线程的回收5. 线程的退出6. 线程的取消7.

python删除xml中的w:ascii属性的步骤

《python删除xml中的w:ascii属性的步骤》使用xml.etree.ElementTree删除WordXML中w:ascii属性,需注册命名空间并定位rFonts元素,通过del操作删除属... 可以使用python的XML.etree.ElementTree模块通过以下步骤删除XML中的w:as

SpringBoot开发中十大常见陷阱深度解析与避坑指南

《SpringBoot开发中十大常见陷阱深度解析与避坑指南》在SpringBoot的开发过程中,即使是经验丰富的开发者也难免会遇到各种棘手的问题,本文将针对SpringBoot开发中十大常见的“坑... 目录引言一、配置总出错?是不是同时用了.properties和.yml?二、换个位置配置就失效?搞清楚加