iOS-Strong/Copy修饰词

在iOS中,string是用strong修饰还是用copy修饰?它们有什么区别呢?本文主要就来讨论这两个问题,在此之前,我们需要知道两个术语,浅拷贝和深拷贝

浅拷贝:指对内存地址的复制,让目标对象指针和源对象指向同一片内存空间,当内存销毁的时候,指向这片内存的指针需要赋值,要不然会成为野指针 深拷贝:指对对象具体内容复制,重新分配对象的内存地址,拷贝结束之后,两个对象虽然值是相同的,但是内存地址不一样,两个对象也互不影响,互不干涉

上代码,测试一下

NSString *str = @"test";
NSString *copyStr = [str copy];
NSMutableString *mutStr = [str mutableCopy];
    
NSLog(@"指针地址:str:%p--copyStr:%p--mutStr:%p",&str,&copyStr,&mutStr);
NSLog(@"内存地址:str:%p--copyStr:%p--mutStr:%p",str,copyStr,mutStr);

运行结果:

指针地址:str:0x16fb31678--copyStr:0x16fb31670--mutStr:0x16fb31668
内存地址:str:0x1002d4080--copyStr:0x1002d4080--mutStr:0x1c024af80

可以看出:copy实现了一次浅拷贝,mutableCopy实现了一次深拷贝 实际上,对于copy和mutableCopy我们可以得出下表的结论

理解了copy作用,我们就不难理解属性中的copy和strong了,实际上在属性中copy比strong多了一步,即在setter方法中

- (void)setName:(id)name{
    _name = [name copy];
}

举个例子:假设有这样一段代码

@property(copy)id obj;

self.obj = object;

此时obj是什么呢?有下面两种情况:
1. object是不可变对象,将会把object浅拷贝一次,赋值给obj
2. object是可变对象,将会把object深拷贝一次,赋值给obj
如果obj是用strong修饰的,就没有拷贝一说了,将会直接把object赋值给obj

在内存计数方面
strong 会使object引用计数+1,obj的引用计数为1
copy   如果object是不可变对象,object引用计数+1,obj的引用计数为1
       如果object是可变对象,会将object深拷贝一份,object的引用计数不会变,obj的引用计数为1

综上所述,我们可以得出以下结论

  1. 当属性本身是可变对象时 此时只能用strong修饰,因为如下图,下图中,name属性经过setter时,得到的永远是不可变对象,当调用可变方法时,就会崩溃
  1. 当属性的赋值来源是可变对象时,如下图,看日志输出,发现当使用strong时,来源发生改变,属性值会跟着发生改变,当实用copy时,来源发生改变,属性不会跟着变
  1. 当属性的赋值来源是不可变对象时,如下图,发现strong和copy并没有什么区别

所以我们在选用修饰词时,我们要根据,属性本身是否可变,对属性赋值的来源是否可变,属性是否需要跟随来源的变化而变化等情况来选用属性的修饰词,不过,在实际开发中,大多数情况都是用copy

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏程序你好

C# 7.3新特性一览

953
来自专栏编程微刊

JS数组去重的6种算法实现以上就是为大家提供的6种JS数组去重的算法实现,希望对大家的学习有所帮助。

1992
来自专栏微信公众号:Java团长

Java编程思想重点笔记(Java开发必看)

Java编程思想,Java学习必读经典,不管是初学者还是大牛都值得一读,这里总结书中的重点知识,这些知识不仅经常出现在各大知名公司的笔试面试过程中,而且在大型项...

1453
来自专栏Pythonista

封装与扩展性

封装在于明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者的代码;而外部使用用者只知道一个接口(函数),只要接口(函数)名、参数不变,使用者的代码...

863
来自专栏塔奇克马敲代码

第 16 章 模板与泛型编程

1262
来自专栏C/C++基础

C++ struct与union

编码运行环境:VS2012+Win32+Debug Win32既表示运行平台是Windows 32bits操作系统,又表示生成32bits的应用程序。

741
来自专栏Web 开发

JavaScript的对象引用

在一个函数体内,var变量声明的变量,其作用域只在该函数体内,对于函数体外而言,是不可见的(废话)。

750
来自专栏北京马哥教育

对Python老司机99%有帮助的简明语法总结乱编

本文由马哥教育Python实战开发班6期学员推荐,转载自互联网,作者为赖笔小新,感谢作者的辛苦付出和贡献。 最近发现进入python群的朋友都在你是如何自学py...

2927
来自专栏维C果糖

编程思想 之「异常及错误处理」

在 Java 的异常及错误处理机制中,用Throwable这个类来表示可以作为异常被抛出的类。Throwable对象可以细分为两种类型(指从Throwable继...

9696
来自专栏张善友的专栏

C# 4.0 Optional Parameters 和Named Parameters

Optional Parameters 是C# 4.0的特色之一,可减少重载函数的数量,却可达到相同的效果,加快开发效率。在使用上就跟C++一样,只需用等号为函...

2047

扫码关注云+社区