2010-06-18 29 views
2

我見過很多iPhone的例子,使用IBOutlet作爲一個字段鏈接到Interface Builder中的UI控件,並且該字段也被定義爲接口類中的屬性。例如,下面的代碼是來自蘋果的示例代碼相似的:是否需要爲IBOutlet字段定義屬性?

// in .h file 
@interface MyViewController : UIViewController { 
    IBOutlet UILabel* _firstName; 
    IBOutlet UILabel* _lastName; 
    ... 
} 

@property (nonatomic, retain) UILabel* firstName; 
@property (nonatomic, retain) UILabel* lastName; 
... 
@end 

// in .m file 
@implementation MyViewController { 
@synthetic firstName = _firstName; 
@synthetic lastName = _lastName; 
... 
@end 

我試圖標籤在Interface Builder鏈接到我的控制器類IBOutlets,我可以看到_FirstName和_lastName。由於鏈接直接從Interface Builder到我的接口類成員(如果我放置@private指令,甚至是私有的)。我是否需要爲這些字段定義屬性?

其實,我試圖刪除這些屬性,似乎我的代碼工作正常。通過定義屬性,我的班級將他們公開。我沒有任何用法或理由將它們作爲我的代碼內或代碼外的屬性。我的問題是,如果這種做法將領域定義爲屬性,是必要的?我是否會錯過任何可能從Objective-C概念或框架調用的內存管理?

+0

可能的重複[如果我不保留IBOutlet,會發生什麼?](http://stackoverflow.com/questions/1250518/what-happens-if-i-dont-retain-iboutlet) – Vladimir 2010-06-18 21:15:48

+0

您可以聲明實現文件中類屬性中的屬性,因此這些屬性不會公開爲公共方法。 – Vladimir 2010-06-18 21:17:34

+0

另請注意,帶有下劃線的ivars前綴非常不受蘋果公司的歡迎,並可能導致問題出現。我認爲這是因爲他們自己的內部類使用它們來避免名稱衝突。 – 2010-06-19 03:00:22

回答

1

由於Jeremie Wekdin提到,我的問題是以某種方式重複。類似的問題和答案顯示,在使用nib/xib文件的情況下,需要考慮內存問題。

總之,Cocoa會先找到setOutletName,然後用property方法設置UI控件對象;否則,Cocoa會直接設置類成員變量並保留它。這意味着應該使用dealloc方法釋放已存檔的對象。

這很好。但是,在我的問題的情況下,我的字段變量具有不同的名稱與其相應的屬性名稱,如_firstName和firstName。在這種情況下,我認爲Cocoa不夠聰明以找出屬性方法,並且從nib/xib中檢索的對象直接設置爲類成員。

爲了驗證它,我覆蓋二傳手:

// in .m file 
@implementation MyViewController { 
@synthetic firstName = _firstName; 
- (void) setFirstName:(UILabel*) value { 
    NSLog("_firstname: %@", _firstName); 
    [_firstname autorelease]; 
    _firstName = [value retain]; 
} 

然後我打開我的看法,日誌信息不會在Xcode的控制檯輸出顯示。但是,如果我保持變量名稱和屬性名稱相同。我看到的setter被稱爲:

// in .h 
@interface MyViewController : UIViewController { 
IBOutlet UILabel* firstName; 
... 
} 

@property (nonatomic, retain) UILabel* firstName; 
... 
@end 

// in .m file 
@implementation MyViewController { 
@synthetic firstName; 
- (void) setFirstName:(UILabel*) value { 
    NSLog("firstName: %@", firstName); 
    [firstName autorelease]; 
    firstName = [value retain]; 
} 
... 
@end 

在輸出控制檯,當視圖中顯示,我看到:

firstName: (null) 

由於複製 QA建議,我讀了Appl's Resource Programming Guide。查找部分中的文檔筆尖對象生命週期,對象加載過程和#3插座連接。您應該看到Mac OS X和iPhone OS有不同的方式將插座連接到對象。 「在iPhone OS,筆尖加載代碼使用setValue:forKey:方法重新連接各出口」

所以,我想下面的代碼:

@implementation MyViewController { 
@synthetic firstName = _firstName; 
- (void) setValue:(id) value forKey:(NSString*) key { 
    NSLog("forKey: %@; value: %@", key, value); 
    if ([key isEqualToString:@"_firstName"]) 
    // It should then call the accessor or property 
    // self._firstName = value; 
    // to set value, like the follow codes in the setter: 
    [_firstName autorelease]; 
    _firstName = [value retain]; 
    } 
    ... 
} 
... 
@end 

我又重新編譯我的代碼,我沒有看到所有的屬性setter調用,包括關鍵_firstName。繼續從Apple的文檔:

「該方法(setValue:forKey :)類似地尋找一個適當的訪問器方法,並在失敗時回退到其他方式。」

這解釋了爲什麼在我的情況下(屬性名稱不同於出口變量名稱)該屬性由Cocoa調用。

總之,當使用IBOutlet和nib/xib(作爲加載視圖的方式)來控制字段時,存在內存問題。讓Cocoa找到一個定義的訪問器或屬性來設置一個處理保留對象的字段變量是很好的。如果您爲IBOutlet字段變量定義屬性,則兩者應該相同。因此,這些代碼可以在Mac OS X和iPhone OS上運行。

相關問題