iOS中的深浅拷贝

2021-03-30  本文已影响0人  树袋熊老公

深浅拷贝问题想必每一个iOS开发都接触过,也是面试过程中最常考的点。网上帖子很多,说法却都不一,很容易把人绕晕,还列了各种表格,我认为记那些结论意义不大,要想彻底搞明白深浅拷贝,不犯晕,核心要记住五个概念:
深拷贝、浅拷贝、copy方法、mutableCopy方法、copy修饰符

根据上述内容,回答以下面试常问的问题:
1.用copy修饰符修饰以后,一定会拷贝一份新的内存地址吗?原对象的引用计数一定不会变吗?

不一定。用copy修饰的属性,在setter时,会先调用传入对象的copy方法得到一份拷贝后再retain,但不同的对象调用copy方法,可能是深拷贝也可能是浅拷贝,如果是浅拷贝,则两个指针指向一个内存,旧对象引用计数会加1。如果是深拷贝,则retain只会是新的对象引用计数加1,不影响旧对象。

2.不可变对象用strong修饰会有什么问题?

如果赋值的对象是不可变对象,那和copy一个效果,都是两个指针指向一个内存,引用计数加1。如果赋值的对象是可变对象,两个指针指向同一个内存则会出现问题。指针类型和实际对象类型不匹配,明明是不可变对象,但是内容却可能会被篡改。这样不符合语义,数据可能出现污染。

3.可变对象用copy修饰会有什么问题?

copy方法会返回一个不可变对象,指针类型和实际对象类型不匹配,调用可变对象的一些方法时则会报错。

总结:2、3两个问题根本原因是因为iOS的消息机制,方法的绑定不在编译期而是运行时确定。为了避免可变对象找不到方法crash,或者不可变对象被篡改,iOS中的不可变对象、容器一般都使用copy修饰符,保证setter方法中对传入的新对象调用copy方法。iOS中的可变对象、容器一般使用strong修饰符,避免setter方法中对传入的对象调用copy方法。

上一篇下一篇

猜你喜欢

热点阅读