[英]Which is the best way to define private methods for a class in Objective-C?
[英]Private properties and methods in Objective-C
在查看 Apple 的一個示例時,在 TableViewController.m 中,他們有這個:
// Private TableViewController properties and methods.
@interface TableViewController ()
@property (nonatomic, retain) NSMutableArray* sectionInfoArray;
@property (nonatomic, retain) NSIndexPath* pinchedIndexPath;
@property (nonatomic, assign) NSInteger openSectionIndex;
@property (nonatomic, assign) CGFloat initialPinchHeight;
... more properties and methods
@end
@implementation TableViewController
... usual stuff
我想知道他們為什么將這些屬性放在 .m 文件中,以及它是如何私有的。 似乎任何導入 TableViewController.m 文件的人都可以使用這些屬性和方法,對吧? 為什么不在.h 文件中使用@private?
他們所做的是在 class 上聲明一個類別,但由於這是在 .m 文件中完成的,因此這些方法是“不可見的”。
然而,這並不意味着不能從外部調用這些方法。 這是因為目標 c 中沒有真正的隱私,因為我們處理的是消息,而不是方法調用。 這意味着您可以向 object 發送消息,即使您不知道 object 是否實際實現了您嘗試調用的方法。 接收 object 將在運行時確定它是否可以處理此調用,甚至可能會轉發它,並且調用 object 是否知道該方法沒有區別。
這就是為什么可以調用私有 API 並因此被拒絕的原因之一。
AFAIK
a) 您不能將屬性標記為 @private in.h - 這僅適用於 ivars。
b) 如果您只是 import.m 文件(在.h 文件中沒有接口定義),您將無法引用您的 class。 如果你這樣做 - 你會在鏈接過程中得到重復的符號。
c)所以是的,這些屬性是私有的,因為它們不能作為常規屬性從外部訪問 - 這些屬性只能使用顯式消息訪問 - 但是在這種情況下你會收到編譯器的警告,或者你可以使用 KVC
他們不是私人的。 它們是匿名屬性,因為它們是匿名類別的一部分。
屬性的好處之一是將擁有的 object 的 memory 管理語義放在一個地方。 考慮一下:
@property (nonatomic, assigned) NSString *assigned;
@property (nonatomic, copy) NSString *copied;
@property (nonatomic, retain) NSString *retained;
在這三種情況下,您可以像這樣分配它們,而無需知道它們的 memory 語義是什么:
self.assigned = stringParameter; // assigns to instance variable
self.copied = stringParameter; // copies, assigns copy to instance variable
self.retained = stringParameter; // retains, assigns to instance variable
在所有三種情況下,您都可以使用相同的代碼進行免費清理:
self.assigned = nil; // this just nils the instance variable
self.copied = nil; // releases copy in ivar, nils instance variable
self.retained = nil; // releases ivar (same as original object),
// nils instance variable
這就是為什么您經常會看到本地屬性:它讓編碼人員在每次想要分配給實例變量時跳過編寫所有 memory 管理邏輯。 這是一個主要優勢,因為您只需更改 @property 即可在整個 class 中更改@property
管理邏輯。
匿名屬性的另一個用途是將聲明為只讀的屬性擴展到外部代碼,以對 class 本身進行讀/寫。
在.h:
@property (nonatomic, readonly, retain) NSError *lastError;
In.m,在匿名類別中:
@property (nonatomic, readwrite, retain) NSError *lastError;
在.m代碼的其他地方:
self.lastError = error;
同樣,這主要是出於 memory 管理原因。
以下是沒有屬性的 _lastError 實例變量的每個賦值。
假設我們在 .h 文件中定義了一個名為 _lastError 的 NSError。
保留:
[_lastError release];
_lastError = [error retain];
帶副本:
[_lastError release];
_lastError = [error copy];
分配:
_lastError = error;
在前兩種情況下,您需要在您的 dealloc 中使用它:
[_lastError release];
但在最后一種情況下,你必須在 dealloc 中不放任何東西,否則你會崩潰。
因此,讓我們添加我們需要使用屬性的內容:
將此添加到匿名類別中:
@property (nonatomic, readwrite, retain) NSError *lastError;
在@implementation 中添加:
@synthesize lastError = _lastError;
另請注意,此時在“現代”Cocoa 運行時(64 位 Mac 或 iOS)上,您可以從 header 中刪除 NSError *_lastError。 編譯器可以根據@synthesize 找出你想要的。
以下是它如何改變我們的代碼:
每個任務:
self.lastError = error; // works regardless of storage specifier
在代洛克:
self.lastError = nil; // works regardless of storage specifier
首先,您通常不能導入一個 .m 文件 - 並非沒有大量編譯器/鏈接器錯誤。 其次,這些屬性是私有的,因此 Apple 可以在后續版本中自由更改它們。
是的,您可以通過反射找到它們。 但這是一個滑坡,等等等等,后果自負,除非你確切地知道自己在做什么,否則會在以后的版本中中斷等等等等。
目標 c 中沒有私有方法或變量,@private 標志主要在那里,所以當其他開發人員查看它時,他們知道它應該是私有的。 你在蘋果代碼中看到的是一個類別的例子,一種在目標 c 中偽造私有方法和變量的方法。 因為外部類只會導入 .h 文件,所以他們永遠不會看到 .m 文件中添加的方法和變量。
使用匿名類別黑盒其他類不應該知道的內部屬性和方法。 盡管當從其他類引用此 class 時編譯器不知道它們,但從技術上講,您可以使用鍵值編碼從其他 class 訪問這些屬性中的任何一個。
不能導入實現文件TableViewController.m
,只能導入TableViewController
的.h
文件,
雖然,您可以在TableViewController class 之外引用這些屬性,並帶有顯示“未響應”注釋的警告。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.