2015-12-16 41 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

相关问题