swift4打印对象的地址分析:copy还是strong

在OC中,对属性显示声明为copy或者strong,让我们知道要操作的对象是否为同一个地址。
但是在Swift中,我们通过let、var时,并不能第一时间知道到底是哪种方式。
比如OC中:

@property(nonatomic,strong) NSMutableArray *dataSource;

我们改变dataSource数组里的内容,dataSource的地址不变。
在Swift中会如何呢?

var arr1 = ["a","b","c"]
var arr2 = arr1
arr1.remove(at: 0)

那么此时arr1和arr2的内容相同吗?
如果改变var和let呢?

var arr1 = ["a","b","c"]
let arr2 = arr1
arr1.remove(at: 0)

再或者,arr1和arr2的地址一样吗?
咱们从地址开始分析,首先Swift中如何打印对象的地址呢?Swift语言成长中,波动较大,但目前已趋于稳定。
从Swift4开始,使用

Unmanaged.passUnretained(obj).toOpaque()

之前的let adress = String.init(format: "%p", arr)unsafeaddressof都已无效。
定义一个打印地址的方法:

func printAddress(values:AnyObject...){
    for value in values {
        print(Unmanaged.passUnretained(value).toOpaque())
    }
    line()
}
func line(){
    print("----------------")
}

单例验证地址

首先从一个单例开始,看是否每次取到的都是同一个地址

final class Single:NSObject{
    static let shared = Single()
    private override init(){

    }
}

var s1 = Single.shared
var s2 = Single.shared
var s3 = Single.shared

printAddress(values: s1 as AnyObject,s2 as AnyObject,s3 as AnyObject)

打印结果:

单例.png

总结
多次获取单例对象,得到是同一个地址。

基本类型

var a1 = 5
let b1 = a1
a1 = 8
print(a1,b1)
printAddress(values: a1 as AnyObject,b1 as AnyObject)

let a2 = 5
let b2 = a2
printAddress(values: a2 as AnyObject,b2 as AnyObject)

let a3 = 5
var b3 = a3
b3 = 8
print(a3,b3)
printAddress(values: a3 as AnyObject,b3 as AnyObject)

var a4 = 5
var b4 = a4
a4 = 8
print(a4,b4)
printAddress(values: a4 as AnyObject,b4 as AnyObject)

打印结果:

image.png

总结:

  • 同一个内容,同一个地址。
  • 改变了内容,新的地址。

String

var str10 = "hello"
var str11 = str10
print(str10,str11)
printAddress(values: str10 as AnyObject,str11 as AnyObject)
str10 = "word"
print(str10,str11)
printAddress(values: str10 as AnyObject,str11 as AnyObject)
line()
var str12 = "hello"
printAddress(values: str10 as AnyObject,str11 as AnyObject,str12 as AnyObject)
line()

由于有了上次的规律,这次不再let给let,let给var,var给let三种情况进行验证,而是对改变内容来验证。
总结

  • 同一个内容,同一个地址。
  • 改变了内容,新的地址。

需要注意的是,Swift中的String不同于OC中的NSString(继承自NSObject),并不是一个类,而是结构体。


image.png

NSString

var nsstr = NSString.init(string: "hello")
let nsstr1 = nsstr
print(nsstr,nsstr1)
printAddress(values: nsstr,nsstr1)
nsstr = "word"
print(nsstr,nsstr1)
printAddress(values: nsstr,nsstr1)

let nsstr2 = NSString.init(string: "hello")
printAddress(values: nsstr,nsstr1,nsstr2)

同理测试NSString在Swift中使用let、var的情况:

[图片上传失败...(image-9490b2-1542338521750)]

总结

  • 同一个内容,同一个地址。
  • 改变了内容,新的地址。

Array

先来验证开篇的问题,AViewController中的dataSource数组,传递给BViewController,在BViewController中改变这个数组内容,A中会变吗?

var arr1 = ["a","b","c"]
var arr2 = arr1
print(arr1,arr2)
arr1.remove(at: 0)
print(arr1,arr2)

image.png

总结
改变arr2,并不会影响arr1的内容。

看一下地址的变化吧:

var arr1 = ["a","b","c"]
var arr2 = arr1
print(arr1,arr2)
printAddress(values: arr1 as AnyObject,arr2 as AnyObject)
arr2.remove(at: 0)
print(arr1,arr2)
printAddress(values: arr1 as AnyObject,arr2 as AnyObject)
arr2.append("d")
print(arr1,arr2)
printAddress(values: arr1 as AnyObject,arr2 as AnyObject)
arr1.remove(at: 0)
print(arr1,arr2)
printAddress(values: arr1 as AnyObject,arr2 as AnyObject)

进行了一波骚操作,然后得到了一个我不太明白的地址变化:

image.png

额,这个地址变化的我猝不及防,ANYWAY,我们还是能得出这个结论:
总结
不管你是let给var,还是var给let还是var给var,改变任意一个变量的值,均互不影响。即:地址相互独立。

结构体

var my = MyStruct.init(height: 5)
var my1 = my
my.height = 10
print(my1.height)

结果:5
嗯,看一下你地址

var my = MyStruct.init(height: 5)
var my1 = my
printAddress(values: my as AnyObject,my1 as AnyObject)
my.height = 10
print(my1.height)
printAddress(values: my as AnyObject,my1 as AnyObject)

结果:
0x00007fd827d2f9e0
0x00007fd827d2fa10
5
0x00007fd827d306c0
0x00007fd827d30370
这个...算了,不看了,毕竟我解释不了的东西,拿出来就是坑...
反正!我就是得到这个结论:
总结:互不影响。

Class

额,这个其实不用测了,因为这个肯定是影响的。

class Person {
    let name:String
    var age:Int
    init(name:String,age:Int) {
        self.name = name
        self.age = age
    }
}

let xm = Person.init(name: "xiaoming", age: 15)
let r = xm
printAddress(values: xm,r)
xm.age = 5
print(xm.age,r.age)

printAddress(values: xm,r)

结果是:

image.png

不过!类的数组是相互独立的!
常见的就是两个类之间传递数据,那么数组被传递过去即为copy,无法相互影响数据内容。

image.png

总结:
改变ps数组的内容,psb不变。

实际问题

所以像是先var一个变量,取出来需要改变的值,那么就无法再改回去了。
举个例子:创建一个人,名字叫晓明,有右手和左手,然后我们想要去掉他的一个手,让他成为杨过。

image.png

结果:晓明还是俩手。
我们上面已经知道了,数组是copy的,copy后互不影响的,那咱们试试改名字:

image.png

结果:“晓明”成功改为了“黄明”。

是不是就不能让晓明断手,成为杨过了呢?
NO,直接断他的手就行了啊。

image.png

作者:XueYongWei
链接:https://www.jianshu.com/p/0ceef8822080

你可能感兴趣的:(swift4打印对象的地址分析:copy还是strong)