2014-12-19 24 views
2

我有一個包含枚舉屬性的類,我想用plist文件使用方法setValuesForKeysWithDictionary:來初始化它的實例。但該文件可能包含無效值。該方案如下:

在文件 'MyClass.h':更好的方法來覆蓋原子屬性設置爲ARC和線程安全的Objective-C

typedef NS_ENUM(NSInteger, FruitTag) { 
    Apple = 0, 
    Banana = 1, 
    Orange = 2, 
    Unknown = 3 
}; 

@interface MyClass : NSObject 

@property (strong, nonatomic) NSString *name; 
@property FruitTag tag; 

@end 

plist文件:

<plist version="1.0"> 
<array> 
    <dict> 
     <key>name</key> 
     <string>Apple</string> 
     <key>tag</key> 
     <integer>0</integer> 
    </dict> 
    <dict> 
     <key>name</key> 
     <string>Banana</string> 
     <key>tag</key> 
     <string>1</string> 
    </dict> 
    <dict> 
     <key>name</key> 
     <string>Pineapple</string> 
     <key>tag</key> 
     <string>5</string> 
    </dict> 
</array> 
</plist> 

正如你看到的,最後的鍵值 '5' 是無效的最大枚舉值是'3'!但方法setValuesForKeysWithDictionary:只是設置該值,無論是否有效。所以我想重寫setter,但枚舉屬性是原子的!還有一件事是:我希望它的getter和setter在多線程場景中是安全的。有關這兩個思考,我修改了代碼:

在文件 'Myclass.h':

typedef NS_ENUM(NSInteger, FruitTag) { 
    Apple = 0, 
    Banana = 1, 
    Orange = 2, 
    Unknown = 3 
}; 

@interface MyClass : NSObject 

@property (strong, nonatomic) NSString *name; 
//@property FruitTag tag; 

- (FruitTag)tag; 
- (void)setTag:(NSInteger)aTag; 

@end 

和文件 'Myclass.m' 中:

#import "MyClass.h" 

@implementation MyClass 
{ 
    FruitTag tag; 
} 

- (FruitTag)tag 
{ 
    @synchronized (self) { 
     return tag; 
    } 
} 

- (void)setTag:(NSInteger)aTag 
{ 
    @synchronized (self) { 
     if ((aTag < Apple) || (aTag > Unknown)) { 
      tag = Unknown; 
     } else { 
      tag = aTag; 
     } 
    } 
} 

- (void)print 
{ 
    @synchronized (self) { 
     NSLog(@"the tag is: %d", tag); 
    } 
} 

@end 

嗯,它看起來很奇怪,但是在我使用方法setValuesForKeysWithDictionary:進行測試時工作正常。但我不確定:是否可以?線程安全嗎?任何潛在的風險?或者更好的重寫方式更受歡迎!謝謝!

+0

我不只是加限定詞「非原子」的枚舉屬性,我希望二傳手可以接受NSInteger的參數,而不是枚舉類型! – kenmux 2014-12-19 03:39:36

回答

0

爲什麼你覺得它看起來很奇怪?你只是手動實現了一個「屬性」並添加了簡單的邊界檢查 - 這是你自己實現一個屬性的好理由。

線程安全嗎?那麼它要麼是它不是,@synchronized肯定是這樣。可能會有更高效,更低層次的使操作線程安全的方法;或者你甚至可能發現沒有什麼特別的東西是「足夠」的;但除非你確定了性能問題,否則不需要去那裏 - 代碼很簡單,你的意圖很清楚。

HTH

+0

嗯,因爲沒有名爲'tag'的屬性,而我使用'setValuesForKeysWithDictionary:'方法。它是否適用於所有情況? (比如iOS的不同版本)。另外一件關於線程安全的東西,在我的代碼中,當getter和setter同時被調用時,它可以嗎? '@ synchronized'對第三個方法'print'做同樣的工作? – kenmux 2014-12-20 04:41:04

+1

'@ property'只是兩種方法的縮寫,你剛纔寫了兩種方法 - 不要認爲它很奇怪。是的,你已經調整了setter的類型,但不是一個糟糕的方式 - 也許把它看作一個*鴨子屬性*如果這有助於:-) – CRD 2014-12-20 04:52:21

+1

'@synchronized(self)'是'self'上的一個鎖 - 它的全部目的是處理兩個或多個方法可能同時被調用(來自不同線程)並且需要被迫一次執行一個的情況。所以是的,您可以同時調用setter,getter和print方法,並且它們將按順序執行(按某種順序)。 – CRD 2014-12-20 04:55:21