Swift Combine - 观察 属性 in object inside of N objects array and merge with other properties

Swift Combine - Observe property in object inside array of N objects and merge with other properties

我正在为 iOS 构建图形应用程序。这是我的代码。

class Group {

    /// All the shapes contained in the group
    public var shapes: CurrentValueSubject<[Shape], Never>

    /// The frame of the group
    var frame: CurrentValueSubject<CGRect, Never>

    /// The path to be calculated and displayed to users from the contained shapes
    var cgPath: CurrentValueSubject<CGPath, Never>
}

class Shape {
    var path: CurrentValueSubject<Path, Never>  = .init(Path())
}

struct Path {
    public var points = [CGPoint]()
}

所以,这就是我想做但不知道如何使用 Combine 做的事情。

我希望Group观察它自己的frameshapes和它的path形状(我需要合并所有这些),所以每次他们每个人都改变了,我可以计算出要显示的新 CGPath 并将其分配给 cgPath 属性(绘制所有内容的视图将观察到)。

请告诉我这是否可行,或者是否有更好的方法。

提前致谢。

使用 CombineLatest

只需将 @Published 属性 包装器添加到您感兴趣的属性中。Combine 已经有一个预定义的 CombineLatest3 方法来创建您可以订阅的 Publisher到。玩得开心。

import Foundation
import Combine
import CoreGraphics

class Group {

    init(shapes: [Shape], frame: CGRect, path: Path) {
        self.shapes = shapes
        self.frame = frame
        self.path = path
        self.observer = Publishers.CombineLatest3($shapes, $frame, $path)
            .sink(receiveCompletion: { _ in }, receiveValue: { (combined) in
                let (shapes, frame, path) = combined
                // do something
                print(shapes, frame, path)
            })
    }

    @Published var shapes: [Shape]
    @Published var frame: CGRect
    @Published var path: Path

    private var observer: AnyCancellable!
}

class Shape {
    var path: CurrentValueSubject<Path, Never>  = .init(Path())
}

struct Path {
    var points = [CGPoint]()
}

注意每次更改如何触发接收器关闭。

let group = Group(shapes: [Shape(), Shape()], frame: CGRect.zero, path: Path())
group.shapes = [Shape(), Shape(), Shape()]
group.frame = CGRect(x: 1, y: 1, width: 1, height: 1)
group.path.points = [CGPoint(x: 1, y: 1)]