3 回答
TA貢獻1799條經驗 獲得超9個贊
雖然丹尼爾的答案是正確的,但我認為它沒有抓住重點。即:
我發現使用屬性代替普通的舊ivars會花費太多代碼,并且如果您對內存管理感到滿意,我不會真正看到好處。
好處是一致性;一致的內存管理和一致的行為。
值得注意的是,這兩行代碼實際上在運行時可能具有截然不同的行為:
iVar = [foo retain];
self.iVar = foo;
第一個是實例變量的直接設置,并且不會有更改通知。第二個過程通過setter進行,因此在設置時保留所有子類自定義項,并確保將更改通知給屬性的所有觀察者。
如果您在整個代碼中直接使用ivars(在類內部-如果您直接從實例外部使用實例的ivars,那么……在您的代碼庫上工作的任何承包商都應將其費率提高一倍;),那么您必須也可以手動處理更改通知傳播(通常通過調用willChangeValueForKey:/ didChangeValueForKey),也可以顯式設計應用程序以避免使用依賴于鍵值觀察的機制。
您說“花費太多代碼”。我沒看到 在以上兩行代碼中,點語法的字符較少。即使使用傳統語法調用setter方法,代碼也更少。
并且不要在集中式內存管理中貶低價值;在大量的呼叫站點和崩潰的城市中,一個偶然的遺漏。
TA貢獻1836條經驗 獲得超13個贊
對于私有字段-我建議僅對原始類型(BOOL / int / float等)使用直接ivars是安全的。我發現將與內存管理相關的所有內容包裝到屬性中的一種很好的做法-甚至是很少使用的字段。這種方法的額外好處是,IDE通常以不同的方式突出顯示直接ivar訪問,因此您始終可以將簡單的標量字段和對象類型字段很好地分開。
與此相反,我強烈建議不要在類公共接口中使用任何直接方法。由于語言的動態性質,它可能導致運行時錯誤,這些錯誤非常難以查找,本地化和修復。考慮以下層次
@interface BaseControl
...
@end
@interface Label : BaseControl
...
@end
@interface Button : BaseControl {
@public
BOOL enabled;
}
@end
和一個代碼片段
- (void)enableAllButtons {
NSArray *buttons = [self getAllButtons]; // expected to contain only Button instances
for (Button *button in buttons) {
button->enabled = YES;
}
}
現在,假設-getAllButtons邏輯中某處存在錯誤,并且該數組中還返回了一些Label-這樣,這些Label類實例將缺少分配的ivar??赡芰钊梭@訝的事實是-enableAllButtons在這種情況下不會崩潰。但是到那時,那些Label實例的內部結構已損壞,當在其他地方使用它們時,這將導致不確定的行為并崩潰。
就像內存管理中的一些常見問題(通常是指針懸而未決)一樣,這種問題很難找到和定位,因為錯誤的出現通常與時間(從時間,代碼或應用程序流而言)相距甚遠。位置,導致錯誤。但是對于這個特定問題,您甚至沒有方便的工具(例如泄漏/僵尸分析儀等)來幫助您進行本地化和修復-即使您學會了如何重現它并可以輕松地研究錯誤狀態。
顯然,如果您使用@property (assign) BOOL enabled;-enableAllButtons,將獲得易于診斷和修復的運行時異常。
- 3 回答
- 0 關注
- 512 瀏覽
添加回答
舉報
