如何使用Swift和KVO观察单个数组元素的变化(更新)? [英] How to observe individual array element changes (update) with Swift and KVO?

查看:163
本文介绍了如何使用Swift和KVO观察单个数组元素的变化(更新)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要订阅/取消订阅数组的各个元素吗?

Do I need to subscribe/unsubscribe to individual elements of an array?

我想分别更新每个表视图单元格,以反映支持数组中的更改.通过更改,我的意思不是添加/删除操作,而是更新数组对象的属性. 我希望我能够解释我想要实现的目标. 谢谢

I want to update each table view cell individually to reflect changes in the backing array. By changes I mean not append/remove operations but update of the properties of the objects of the array. I hope I was able to explain what I want to achieve. Thanks

推荐答案

要使用KVO,请声明具有dynamic属性的模型对象:

To use KVO, declare the model object with dynamic properties:

class Foo: NSObject {
    @objc dynamic var bar: String   // in Swift 3, `@objc` is not necessary; in Swift 4 we must make this explicit

    init(bar: String) {
        self.bar = bar
        super.init()
    }
}

然后,让单元处理KVO.首先,我有一个协议,通过该协议,单元可以通知表视图需要重新加载它:

Then, let the cell process the KVO. First, I'd have a protocol by which the cell can inform the table view that it needs to be reloaded:

protocol CustomCellDelegate: class {
    func didUpdateObject(for cell: UITableViewCell)
}

并且表视图控制器可以遵循此CustomCellDelegate协议,并在得知需要执行以下操作时重新加载单元格:

And the table view controller can conform to this CustomCellDelegate protocol and reload the cell when informed it needs to:

func didUpdateObject(for cell: UITableViewCell) {
    if let indexPath = tableView.indexPath(for: cell) {
        tableView.reloadRows(at: [indexPath], with: .fade)
    }
}

因此,然后定义要设置和处理KVO的单元.在Swift 4和iOS 11中,您可以将基于闭包的observe方法与新的强类型键结合使用:

So, and then define cell to setup and handle KVO. In Swift 4 and iOS 11, you can use the closure-based observe method with the new strongly typed keys:

class CustomCell: UITableViewCell {

    weak var delegate: CustomCellDelegate?

    private var token: NSKeyValueObservation?

    var object: Foo? {
        willSet {
            token?.invalidate()
        }
        didSet {
            textLabel?.text = object?.bar
            token = object?.observe(\.bar) { [weak self] object, change in
                if let cell = self {
                    cell.delegate?.didUpdateObject(for: cell)
                }
            }
        }
    }
}

在Swift 3中:

class CustomCell: UITableViewCell {

    private var observerContext = 0

    weak var delegate: CustomCellDelegate?

    var object: Foo? {
        willSet {
            object?.removeObserver(self, forKeyPath: #keyPath(Foo.bar), context: &observerContext)
        }
        didSet {
            textLabel?.text = object?.bar
            object?.addObserver(self, forKeyPath: #keyPath(Foo.bar), context: &observerContext)
        }
    }

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        guard context == &observerContext else {
            super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
            return
        }

        delegate?.didUpdateObject(for: self)
    }

    deinit {
        object?.removeObserver(self, forKeyPath: #keyPath(Foo.bar), context: &observerContext)
    }

}

现在cellForRowAtIndexPath可以只设置delegateobject属性:

And now the cellForRowAtIndexPath can just set the delegate and object properties:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CustomCell

    cell.delegate = self
    cell.object = objects![indexPath.row]

    return cell
}

在我看来,这种KVO机制比Swift观察者机制更好,因为模型对象不需要知道(也不应该)关于观察者的任何信息.只需表明它支持动态调度即可.

In my opinion, this KVO mechanism is better than the Swift observer mechanism because the model object doesn't need to know (nor should it) anything about the observer. It just needs to indicate that it supports dynamic dispatch, and that's it.

对于上述的Swift 2格式,请参见此答案的先前版本.

For Swift 2 rendition of the above, see previous revision of this answer.

这篇关于如何使用Swift和KVO观察单个数组元素的变化(更新)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆