[iOS Tutorial] 4 用 property 存取所有變數

八月 26, 2012  Comments by

[iOS Tutorial] 2 中我們提到「好的 property 寫法讓你減少犯錯的機會,隱藏複雜的實作並且讓你的語意更清楚,同時還提供一套明顯的記憶體保護機制。前提是你要會用」。簡單來說,如果我們存取任何變數之前都是透過 setter 和 getter,可以保護此變數受某種程度的存取限制,例如我們希望 maxValue 小於10。

// interface
@property int maxValue

// implementation
– (void)setMaxValue:(int)maxValue { if (maxValue <) _maxValue = maxValue; }

當我們宣告 @property 之後,往往會設定 @synthesize 讓 Xcode 自動幫我們產生 settergetter,除此之外,@property 的屬性 (attribute) 還提供記憶體管理的保護機制,減少我們「忘記釋放」或「釋放過頭」記憶體的機會。

// @interface Member : NSObject
@property (nonatomic, copy) NSMutableArray *mutableAry;
@property (nonatomic, strong) NSArray *myMemberArray;
@property (nonatomic, weak) NSString *myLeader;

ARC (Automatic Reference Counting) 是在 iOS 5 加入的新機制。

  • 在沒有 ARC 之前,我們物件管理記憶體的方式是「我要去游泳,跟管理員登記進到游泳池的人多一人;過一會兒,我要離開,跟管理員登記離開游泳池的人少一人。等到所有人都離開之後,游泳池就可以關門了」,實際上,有人會不小心多登記一次 (管理員半夜還以為有人留在泳池裡),有人不小心多註銷一次 (管理員在泳池還有人的時候就提早關門)。這就是人為的悲劇。
  • 在有 ARC 之後,「我要刷卡過匣門才能進泳池,泳池多一人;要離開時,匣門刷卡離開,泳池少一人。所以人離開後,泳池自動關門」。自動化的好處。

 

兩者各有優缺點,就像手排車開習慣了,開自排車就會少了操控的樂趣。所以什麼時候用 copy/strong/weak 就今為今日的重點。我們以單一 object 被多個 owner 指向為例。

  • strong – 如果我在 heap 中 strong 指向此物件,除非連同我在內,所有人 (strong) 都不指向此物件,再釋放此物件。否則讓他一直停留在 heap。
  • weak – 如果我在 heap 中 weak 指向此物件,除非所有 strong 指向此物件的人,都不指向此物件,再釋放此物件。當此物件被釋放的時候,會將我的物件指標指向 nil (nil 可暫時看做 C 的 NULL),也就是說 getter 回傳的值為 nil。
  • copy – 除了 strong 的特性外,在 heap 產生一個一樣的物件,並指向此物件。

所以 strong 的含意是,在我不再需要他之前,請保留在 heap。weak 的含意是,可有可無,有就用,沒有就算了。copy 的含意是,不希望我對物件所做的修改影響到其他人。

@property 的 setter/getter 取用方式有兩種方式,以前面的 Member class 為例。

Member *obj = [[Member alloc] init];
// setter
obj.myLeader = @"Jobs";// 或 [obj setMyLeader:@"Job"];
// getter
NSArray *members = obj.myMemberArray; // 或 NSArray *members = [obj myMemberArray];

兩種取用方式,第一種是以 Dot Notation (obj.myLeader = @"Jobs";),第二種是以 message 的方式調用 method ([obj setMyLeader:@"Job"];)。經過這番解說,是不是對 @property 更加清楚了呢?所以「好的 property 寫法讓你減少犯錯的機會,隱藏複雜的實作並且讓你的語意更清楚,同時還提供一套明顯的記憶體保護機制」。

iOS 入門教學

About the author

喜愛攝影、自助旅行、一邊宅在家帶小孩一邊創業的 App 設計師。