2014-09-27 14 views
2

我有一些對象,更準確地說是模型,它們的某些屬性被延遲加載,即在讀取時從服務器獲取。目前,我運用經典技術,例如Objective-C:惰性加載的模型模式

@synthetize description = _description; 
- (NSString *)description { 
    if (!_description) { 
     NSError *error = nil; 
     _description = [NSString stringWithContentsOfURL:url 
           encoding:NSUTF8StringEncoding 
           error:&error]; 
     if (error) { 
      _description = nil; 
      // error handling 
     } 
    } 
    return _description; 
} 

但是,它涉及很多代碼重複。當然,我仍然可以有一個通用的方法來做這件事,並在所有的getter中調用這個方法(這就是我所做的)。但你有更好的主意嗎?

編輯:使註釋中所建議的代碼更安全。這裏是另一個建議:

@synthesis description = _description; 
- (NSString *)descriptionWithCompletion:(void (^)(NSString *description, NSError *error))completion { 
    if (!_description) { 
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
      NSError *error = nil; 
      _description = [NSString stringWithContentsOfURL:url 
            encoding:NSUTF8StringEncoding 
            error:&error]; 
      if (error) _description = nil; 

      completion(_description, error); 

     }); 
    } 
    completion(_description, nil); 
} 
+0

這不是一個好的模式!您的調用者無法處理由此產生的錯誤,並且在網絡訪問完成之前阻止調用線程。這是一個非常好的方式來讓用戶界面口吃,並讓你的應用被操作系統殺死。您可能想要向模型的用戶指示訪問這些值的過程是異步的,並且可能會因爲它們傳遞給您一個完成塊(它帶有一個可選錯誤)而失敗。 – 2014-09-27 14:32:55

+0

所以,你建議讓用戶把一個完成塊傳給getter。然後,在後臺隊列中分派獲取進程,後臺隊列將以對象和錯誤爲參數調用完成塊。我對嗎? – user1553136 2014-09-27 14:43:51

+0

是的,確切地說。但是,這對調用者來說有些痛苦,所以如果可能的話,您可能希望減少這些異步方法的數量,例如通過一次加載整個模型。 – 2014-09-27 14:49:32

回答

0

所以,你想減少的方法是這樣的樣板:

- (NSString *)prop {return [self _genericGetterForProperty:_prop];} 

使用宏是一種選擇;它會減少文本的數量,但是您仍然需要每種方法的一行,所以我不清楚這是否真的值得額外的複雜性。

有一種方法可以通過dynamic method resolution來做到這一點。基本上,你在你的班上實施+ resolveInstanceMethod:。如果有人試圖調用您的模型對象上的一個方法,而這個方法在編譯時並未提供,則會調用它。你可以實現它來檢查選擇器是否與你的xxxWithCompletion:結構匹配。如果是這樣,您可以基於「xxx」值構建實現並將其添加到您的課程中。你可以通過聲明你的屬性爲@dynamic或通過顯式地通過pragmas禁止警告來阻止編譯器警告你。不過,我不推薦它。這是一個複雜而棘手的解決方案;除非你有數百個這些屬性,否則我只會寫樣板文件。 (或寫一個腳本來寫樣板文件。)