美文网首页swift
swift4打印对象的地址分析:copy还是strong

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

作者: XueYongWei | 来源:发表于2018-10-15 12:30 被阅读117次

    在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)
    

    打印结果:

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

    基本类型

    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)
    

    打印结果:

    基本类型
    总结:
    • 同一个内容,同一个地址。
    • 改变了内容,新的地址。

    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),并不是一个类,而是结构体。


    String

    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的情况:


    NSString

    总结

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

    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)
    

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

    array
    额,这个地址变化的我猝不及防,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)
    

    结果是:


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

    实际问题

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


    栗子

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


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

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

    直接断手

    👌

    相关文章

      网友评论

        本文标题:swift4打印对象的地址分析:copy还是strong

        本文链接:https://www.haomeiwen.com/subject/nhkfzftx.html