當前位置:成語大全網 - 書法字典 - ios開發的修改副本

ios開發的修改副本

在開發中,我們常說copy是用來修飾block或者nsstring字符串的。那麽為什麽要用復制而不是強呢?

先做個測試:上圖。

這時我們可以看到,Strong修飾的strongStr只想要原來的地址,而copy修飾的copysStr指向新的內存地址,所以str改變,strongStr隨之改變,而copysStr沒有影響。

當然,很多人看到copy會想到深抄和淺抄的問題。我在上壹篇播客中寫過這個問題,並附上了測試演示:/writer #/notebooks/24598196/Notes/42429579。

在了解了copy和mutablecopy之後,有人會質疑:不是說copy的不可變對象是淺拷貝嗎?這裏,copy修改nsstring,它是壹個不可變的對象。為什麽變成了深度復制?應該是copysstr,應該隨著str變化吧?

接下來,我們繼續研究:上圖。

同樣,copy修改壹個不可變對象nsstring,這裏我們在賦值的時候給壹個不可變對象nsstring,所以不壹樣。首先,分析第壹段。從打印的角度來看,Strong修飾的Str和copy修飾的copysStr都是指向str的內存地址。所以,這裏Copy修改的不可變對象copySSTR就變成了淺拷貝。

分析第二段,我們修改了str的地方,看到str的打印地址變了。本來str屬於不可變的字符串,我們可以修改,因為str = "ddd "相當於開辟了壹個新的內存地址,str指針指向ddd的地址,而不是修改原來str指向hello的內存地址。然後往下看,因為第壹段測試顯示test.strongStr和test.copysStr都是淺拷貝,仍然指向hello的原始地址。指向新地址的str不會改變strongStr和copysStr的值,這裏打印的地址正好印證了這壹點。

我們是否可以認為,雖然副本修改器修改了屬性,但是否是暗副本與屬性類型無關,而是與分配的對象類型有關?

帶著這個疑問,我們繼續探索,如上:

這裏我們用copy修飾了壹個變量數組array,同時我們也給這個數組賦了壹個變量數組temparray。我們在上壹篇博客中已經驗證了,凡是可變或不可變的,復制的就是不可變的。可變對象的副本是深層副本。這裏我們觀察到self.array指向壹個新的內存地址,而不是temparray的,所以向temparray添加新元素不會影響self.array..從錯誤信息來看,我們不能給內存地址為0x600002afbfc0的數組添加元素,也就是說self.array是壹個不可變的數組。至此,我們只剩下最後壹個疑問了。self.array是從temparray還是array復制的?

我始終相信實踐是檢驗真理的唯壹標準。

然後上圖:

這裏我們把壹個不可變數組賦給壹個可變數組,寫錯了,但是不影響調試。從打印的地址來看,self.array和temparray指向同壹個地址0x6000032c7700。當我們向self.array添加元素時,會出現錯誤。至此,全部真相都清楚了,這說明我們的復制修飾數組被輕復制了。我們知道,當不可變對象使用copy時,它只是被輕度復制,然後我們復制修飾壹個可變數組,並賦予壹個不可變數組。

因此,證明了屬性的修飾符與被賦值對象的類型有關,而與當前對象類型無關。

在開發中,我們經常會對自己定義的對象進行什麽類型的賦值,從而誤以為修飾符只與當前屬性的類型有關。

最後的問題是什麽?其實剛才無論是字符串還是數組的驗證,問題都出在點語法上。我們知道sefl.array實際上取的是set賦值方法(_array = array),array是temparray作為參數傳遞的指針,所以set方法的賦值實際上是temparray復制壹個指針。是否創建新的內存地址取決於temparray的類型。

這裏可以解釋壹下為什麽nsstring經常使用copy,因為在修飾copy的時候,當我們的屬性被賦了壹個變量字符串的時候,它會被深度復制成壹個不可變的字符串,這樣即使原字符串發生變化,也不會影響我們的屬性值,保證了屬性的穩定性。

如果妳指定壹個不可變的字符串,它恰好是壹個淺拷貝。不可變的字符串是不能變的,所以上面的str = @“DDD”好像變了。其實對於不可變的字符串來說,這樣寫就意味著開辟了壹個新的內存地址,STR指向新的地址,而原地址仍然被我們的copysStr指向,不會被破壞或者改變,也保證了屬性的穩定性。