2012-07-06 68 views
4

我剛剛從Craig Hockenberry閱讀了一篇關於ARC and copy的簡短博文。我現在的問題是參數傳遞給初始值分配給實例變量總是使用copy?或者它取決於實例變量的類型?初始化程序和副本

#import "MyObject.h" 

@implementation MyObject { 
    SomeType *_ivar1; 
    SomeOtherType *_ivar2; 
} 

-(id)initWithParam1:(SomeType *)param1 andParam2:(SomeOtherType *)param2 
{ 
    if ((self == [super init])) { 
     _ivar1 = [param1 copy]; // Always good 
     _ivar2 = [param2 copy]; // practice? 
    } 

    return self; 
} 

@end 
+1

它看起來像我Craig只是警告設置支持ivar的屬性,它有一個'copy'說明符。 – 2012-07-06 18:26:26

回答

2

取決於變量和意圖的類型。

對於簡單的類型 - NSString,NSArray,NSNumber等 - 您使用複製,因爲您通常希望存儲的類型是不可變的。即在firstName屬性中通過傳入NSMutableString的實例可以在外部對其進行修改,這是沒有意義的。

對於更復雜的類 - 封裝狀態和功能的類 - 您通常不想完全複製它,因爲該狀態可能隨時間而改變。例如,如果您的應用程序是一個流式視頻應用程序,該應用程序有一個VideoPlayer實例播放封裝在StreamingVideo實例中的視頻,則您不想複製StreamingVideo,因爲隨着更多數據下載,其內部狀態將不斷變化(或發生錯誤)。

I.e. copy用於當你想要一個狀態不可變的快照時,並且當你希望對象A連接到B以用於改變/監視/查詢B的狀態時使用引用。

而且,是的,你希望它是一致的。如果一個屬性是copy,並且您有一個設置該屬性的便利初始值設定項,請確保便利初始值設定項還將任何設置複製到該屬性。

+2

我的一般規則:如果被存儲的類型有一個可變的子類,你應該使用copy(屬性和init)。 – 2012-07-07 14:45:33

+0

一個很好的經驗法則。 – bbum 2012-07-07 21:42:53

4

我覺得關鍵是理解的帖子是在此聲明:

因爲我認爲這是一個壞主意時使用存取-init從不使用由@property定義的複製語義和ARC愉快地保留了參考,而不是複製它。

我認爲,克雷格是有關下列情況具體講:

@interface MyObject : NSObject { 
    SomeType *_ivar1; 
} 
-(id)initWithParam1:(SomeType *)param1; 
@property (copy, nonatomic) SomeType* prop1; 
@end 

@implementation MyObject 
@synthesize prop1 = _ivar1; 
-(id)initWithParam1:(SomeType *)param1 { 
    if ((self == [super init])) { 
     /* 
     Craig could have called 

     self.prop1 = param1; 

     but he believes that it's a bad idea to call accessors 
     from the initializer, so he calls copy explicitly. 
     */ 
     _ivar1 = [param1 copy]; 
    } 
    return self; 
} 
@end 
+0

@JohnTopley你會介意解釋你對downvote的理由嗎? – dasblinkenlight 2012-07-07 15:25:42

+0

@dasblikenlight你給出了一個很好的答案,但它不是我真正問過的問題!話雖如此,我認爲downvote可能有點苛刻,但不幸的是我的投票現在被鎖定,除非你編輯你的答案。 – 2012-07-08 09:17:38