ios - 在 Swift 中使用属性观察器修改 UI 组件

标签 ios swift uicollectionview

我创建了 UICollectionViewCell 的子类,用于显示一些信息。我有一个类型为“天气”的属性。当设置了该实例后,我想更新单元格。下面的方法不好吗?我在想,如果我在加载 UI 组件之前访问它,我可能会触发 View 提前创建。或者这是无意义的并且仅适用于 UIViewController (关于尽早使用 view 属性)?

如果这不好,正确的方法是什么?

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

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

最佳答案

不过,您可能需要一个 else 子句,如果 weathernil 则清除文本字段。同样,如果您可能从后台线程更新此内容,您可能希望将该 UI 更新分派(dispatch)回主线程。

请注意,当您在单元格的 init 中设置 weather 时,不会调用此观察者(也不会在以下位置配置 @IBOutlet):无论如何)。因此,请确保您不依赖于此。

此外,如果 Weather 是可变的,请注意,如果您更改现有 Weather 对象的 fromDate,则不会捕获该对象。 (如果 Weather 是可变的,您确实希望通过 KVO、委托(delegate)协议(protocol)模式或其他方式捕获其不断变化的属性。)但是如果您创建 Weather不变的,你应该没问题。


因此,从技术上讲,这就是问题的答案,但这引发了一些设计注意事项:

  1. 人们通常应该努力使不同类型松散耦合,即一种类型不应过于依赖另一种类型的内部行为。但在这里,我们在单元内有一个观察者,它依赖于天气的可变性。

  2. 不建议使用存储属性在 View 中存储模型对象。单元格在滚动到屏幕外时会被重用,但您可能需要一个单独的模型来捕获相关模型对象,然后 Controller 根据需要处理向 View 对象(单元格)提供适当的模型对象。

    <

底线,不建议在“ View ”内使用存储的属性来存储“模型”信息。

您可以通过编写代码来解决这两个问题,该代码清楚地表明您仅使用此天气参数来更新 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 观察者存储的属性是一种有用的模式。但只有当该属性(property)确实是 View 属性(property)时才应该这样做。例如,考虑绘制某种形状的自定义 View 。您可能已存储属性,用于指定绘制路径时要使用的笔划的宽度和颜色等。然后,存储 lineWidthStrokeColor 属性可能有意义,然后您可能有一个 didSet 调用 setNeedsDisplay() (触发 View 的重绘)。

所以,您建议的模式确实有实际应用,只是它应该仅限于属性确实是 View 对象的属性的情况。

关于ios - 在 Swift 中使用属性观察器修改 UI 组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34324273/

相关文章:

ios - iOS 中密码字段的字母数字验证

ios - 使用泛型时的 EXC_BAD_ACCESS

iphone - 在下载文件之前检查 iphone 设备上是否有足够的空间

swift - 从本地存储加载 UIImages 到 collectionView 非常慢

ios - Swift 中的大 JSON 文件

ios - 如何处理两个容器 View 内的两个 Collection View

ios - 所有未在 UITableView 中呈现的解析对象

swift - HTML 字符串在 MAC Catalyst 中不起作用

objective-c - UICollectionView 和图像

ios - NSObject(RACKVOWrapper)rac_observeKeyPath :options:observer:block: EXC_BAD_ACCESS Crash