一般來說,Extension用來給Class增加私有屬性和方法,寫在 Class 的.m檔案。但是Extension不是必須要寫在.m檔案,你可以寫在任何地方,只要在 @implementation 前定義就可以。所以我們可以利用這個特性實現屬性隱藏。
Case: 模組內部需要訪問某屬性,模組外需隱藏。這種情況經常會遇到。例如對於某一公司來講,每個員工都需要員工ID來唯一標識,但是員工作為自然人,在其他地方,別人不需要知道這個ID。所以對於該員工的ID,在公司內部需要訪問,在外部需要隱藏。
定義一個company物件,一個person物件。
@interface Person : NSObject @property (nonatomic, strong) NSString *name; @end
@interface Company : NSObject @property (nonatomic, strong) NSString *name; - (void)addStaff:(Person *)person; - (void)printAllStaffDisplayName; @end
公司可以增加一個自然人當自己的員工。可以列印全部員工ID,
@interface Company () @property (nonatomic, strong) NSMutableArray<Person *> *staffs; @end @implementation Company - (void)addStaff:(Person *)person { person.companyID = [NSString stringWithFormat:@"大漢%ld",self.staffs.count]; [self.staffs addObject:person]; } - (void)printAllStaffDisplayName { for (Person *staff in self.staffs) { NSLog(@"name:%@ displayName:%@ \n",staff.name,staff.companyID); } } - (NSMutableArray<Person *> *)staffs { if (!_staffs) { _staffs = [NSMutableArray arrayWithCapacity:0]; } return _staffs; } @end
可以看到在 Company 中需要訪問 Person 的 companyID,所以我們給 Person 增加一個 Extention。寫在 Company.h。
@interface Company : NSObject @property (nonatomic, strong) NSString *name; - (void)addStaff:(Person *)person; - (void)printAllStaffCompanyID; @end @interface Person () @property (nonatomic, strong) NSString *companyID; @end
這樣我們就可以在模組內部增加了一個public屬性,而模組外部不知道有這個屬性。
Company *cisco = [Company new]; cisco.name = @"cisco"; Person *tao = [Person new]; tao.name = @"濤"; [cisco addStaff:tao]; [cisco printAllStaffDisplayName];
關於這個特性,可以參考sunny的文章:http://blog.sunnyxx.com/2016/04/22/objc-class-extension-tips/。但是,當你執行的時候會發現,crash了!log顯示找不到setCompanyID方法,原來我們把extention寫在非.m檔案的時候,oc不會幫我們自動生成set,get方法。我想手動寫一個set方法來解決這個問題,發現如果想在 @implenmatation 寫,就必須知道他的例項變數 _companyID,我們現在拿不到。聯想到readOnly屬性可以使用 extention 在.m中修改為readWrite:
.h
@interface Person : NSObject @property (readonly, nonatomic, strong) NSString *gender; @end
.m
@interface Person () @property (nonatomic, strong) NSString *gender; @end @implementation Person @end
那我們也可以在 Person.m 中再次申明一個companyID的私有屬性。這樣,oc會幫我們自動生成set,get方法。試驗一下,完美!
@interface Person () @property (nonatomic, strong) NSString *companyID; @end @implementation Person @end