巧用 Class Extension 隱藏屬性

6度XZ發表於2019-05-09

一般來說,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

Demo下載

相關文章