2015-12-16 82 views
1

我已經創建了顯示一些信息的UICollectionViewCell的子類。我有一個天氣類型的屬性。當一個實例被設置,我想更新單元格。這種方法不好嗎?我在考慮如果在加載之前訪問UI組件,我可能會觸發早期創建的視圖。或者,這是沒有意義的,只適用於UIViewController(關於早期使用view屬性)?使用屬性觀察者修改Swift中的UI組件

如果這是不好的,那麼正確的方法是什麼?

var weather: Weather? { 
     didSet { 
      if let weather = weather {        
       dayLabel.text = dayFormatter.stringFromDate(weather.fromDate) 

       // ... more code like this 
      } 
     } 
    } 

回答

0

如果我計劃在用戶會話期間更新值,我會使用屬性觀察器。如果這是一個只在用戶第一次加載時纔會更新的值,那麼我只是在最初加載視圖時調用一個方法。

如果您使用屬性觀察器,您可以在定義屬性觀察器時給它一個初始值,以便在用戶需要時提供數據。另外,如果您要更新用戶界面,請確保在主隊列上執行此操作。

var weather: Weather = data { 
     didSet {  
      dispatch_async(dispatch_get_main_queue(),{ 
       if let weather = weather {        
        dayLabel.text = dayFormatter.stringFromDate(weather.fromDate) 

       // ... more code like this 
       } 
      }) 
     } 
    } 
3

您可能需要一個else條款,不過,清除文本字段,如果weathernil。同樣,如果您可能會從後臺線程更新它,您可能需要將該UI更新發送回主線程。

請注意,當您在單元格的init中設置了weather(不管怎樣,在此時將配置@IBOutlet也不會調用此觀察者)。所以請確保你不依賴於此。

此外,如果Weather是可變的,則認識到如果更改現有Weather對象的fromDate,則不會捕獲該對象。 (如果Weather是可變的,你真的想通過KVO,委託協議模式或你有什麼來捕捉它的變化屬性。)但是如果你使Weather不變,你應該沒問題。


所以,從技術上說,這就是問題的答案,但是這引起了一些設計方面的考慮:

  1. 一個一般應儘量使不同類型的鬆耦合,即一種不應該過於依賴另一個人的內部行爲。但是在這裏我們有一個觀察者,這個觀察者依賴於Weather的可變性。

  2. 這種使用存儲屬性在視圖內存儲模型對象是不可取的。單元格在屏幕外滾動時可以重複使用,但您可能需要一個單獨的模型來捕獲相關的模型對象,然後控制器根據需要處理向視圖對象(單元格)提供適當的模型對象。

底線,不建議在「視圖」中使用存儲屬性作爲「模型」信息。

您可以通過編寫代碼來解決這兩個問題,這些代碼清楚地表明您僅僅使用此參數來更新UI控件,而不是用於存儲任何內容。因此,而一個存儲的屬性,我只想用一個方法:

func updateWithWeather(weather: Weather?) { 
    if let weather = weather { 
     dayLabel.text = dayFormatter.stringFromDate(weather.fromDate) 

     // ... more code like this 
    } else { 
     dayLabel.text = nil 

     // ... more code like this 
    } 
} 

而這很可能只是從collectionView:cellForItemAtIndexPath:內調用。

但是,這表明你只是更新基於天氣參數的控件,而不是試圖做任何事情。而巧合的是,天氣對象的可變性現在是不相關的,因爲它應該是。如果型號改變,請致電reloadItemsAtIndexPaths:,這將觸發您的collectionView:cellForItemAtIndexPath:被調用。

有些時候,didSet觀察員存儲的財產是一種有用的模式。但是,只有當房產確實是一種看法時才應該這樣做。例如,考慮繪製某種形狀的自定義視圖。您可能已經存儲了指定例如繪製路徑時要使用的筆劃的寬度和顏色的屬性。然後,存儲lineWidthstrokeColor的屬性可能是有意義的,然後您可能會有一個didSet調用setNeedsDisplay()(這會觸發重新繪製視圖)。

因此,您建議的模式確實具有實際應用,只是應該將其限制在屬性是視圖對象屬性的情況。

+0

感謝您的反饋。你有另外一種方法可以做得更好嗎?除了用你描述的要點改進代碼。 – LuckyLuke

+0

奧基,謝謝。在那之前,我留下了「未答覆」的問題。 – LuckyLuke

+0

@LuckyLuke - 順便說一句,除了單元格和'Weather'之間不可靠的緊密耦合之外,使用存儲屬性存儲模型信息的想法也是不可取的。看修改後的答案, – Rob

相關問題