Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/98.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何检测结构中的更改,包括其任何属性或其属性等。?_Ios_Swift - Fatal编程技术网

Ios 如何检测结构中的更改,包括其任何属性或其属性等。?

Ios 如何检测结构中的更改,包括其任何属性或其属性等。?,ios,swift,Ios,Swift,假设我有以下设置: struct Sandwich { var bread: Bread var fillings: [Filling] var slices: Int } enum Bread: String { case white case wholemeal } struct Filling { let name: String let calories: Int } 因此,我们有一个父结构,其中包含一些其他属性、枚举、其他结

假设我有以下设置:

struct Sandwich {
    var bread: Bread
    var fillings: [Filling]
    var slices: Int
}

enum Bread: String {
    case white
    case wholemeal
}

struct Filling {
    let name: String
    let calories: Int
}
因此,我们有一个父结构,其中包含一些其他属性、枚举、其他结构等,作为子结构。他们可能也有自己的孩子

我试图做的是检测我的
三明治的任何更改,发布通知或使用Combine发布更改,等等

这是我的三明治:

var三明治=三明治(面包:白色,馅料:[馅料(名称:“鸡肉”,卡路里:100)],切片:2)

现在,假设我几分钟后来,决定再添加一种填充物:

sandwich.fillings.append(馅料(名称:“莴苣”,卡路里:10)]

或者,也许他们决定增加订单:

sandwich.slices+=2

我想做的是保持循环。我想要一个通知,让我知道我的
Sandwich
是否以任何方式发生了变化,是它的一个子属性发生了变化,还是它的一个孙子的属性发生了变化,甚至是在树的更深处

我还想使用我的
Sandwich
的这些更改版本来构建一个撤销/重做队列,因此每次更改时的状态最好是可记录/可存储的


我意识到我可以编写大量的委托和其他东西来完成这项工作,但我希望在模型发生变化时(即,如果我添加了一个新的属性等),能够自动工作并继续工作。

KVO
Combine
都适用于从
NSObject
继承的类

自动更改需要
运行时


使用
class
,而不是
struct
模型部件: 使用KVO:
使用联合收割机:

class ViewController: UIViewController {

    @objc var food = Sandwich()

    var cancellableFilling: Cancellable?
    var cancellableSlice: Cancellable?

    override func viewDidLoad() {
        super.viewDidLoad()
        // use Combine
        cancellableFilling = food.publisher(for: \.fillings)
                                    .sink(){
                                        val in
                                        print("food.fillings now \(val).")
                                    }


        cancellableSlice = food.publisher(for: \.slices)
                                    .sink(){
                                        val in
                                        print("food.slices now \(val).")
                                    }

    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        food.fillings.append(Filling())
        food.slices += 1
    }

}

最好的办法是在所有变量上都有一个didSet,无论何时调用didSet,您都要记录状态或使用ObservieObject执行您需要的操作?
class ViewController: UIViewController {

    @objc var food = Sandwich()
    var observationFilling: NSKeyValueObservation?
    var observationSlice: NSKeyValueObservation?

    override func viewDidLoad() {
        super.viewDidLoad()
        // use KVO
        observationFilling = observe(\.food.fillings, options: [.new]) { object, change in
            if let val = change.newValue{
                print ("food.fillings now \(val).")
            }
        }
        observationSlice = observe(\.food.slices, options: [.new]) { object, change in
            if let val = change.newValue{
                print ("food.slices now \(val).")
            }
        }
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        food.fillings.append(Filling())
        food.slices += 1
    }

}
class ViewController: UIViewController {

    @objc var food = Sandwich()

    var cancellableFilling: Cancellable?
    var cancellableSlice: Cancellable?

    override func viewDidLoad() {
        super.viewDidLoad()
        // use Combine
        cancellableFilling = food.publisher(for: \.fillings)
                                    .sink(){
                                        val in
                                        print("food.fillings now \(val).")
                                    }


        cancellableSlice = food.publisher(for: \.slices)
                                    .sink(){
                                        val in
                                        print("food.slices now \(val).")
                                    }

    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        food.fillings.append(Filling())
        food.slices += 1
    }

}