【问题标题】:Swift Combine - Observe property in object inside array of N objects and merge with other propertiesSwift Combine - 观察 N 个对象数组内对象中的属性并与其他属性合并
【发布时间】:2020-02-11 08:27:47
【问题描述】:

我正在为 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 观察它自己的frame、shapes 和它的形状的path(我需要合并所有这些),所以每次它们改变时,我都可以计算出新的要显示的 CGPath 并将其分配给 cgPath 属性(绘制所有内容的 View 将观察到该属性)。

请让我知道这是否可行,或者是否有更好的方法来解决所有这些问题。

提前致谢。

【问题讨论】:

    标签: swift combine


    【解决方案1】:

    使用 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)]
    

    【讨论】:

    • group.path.points 赋值行也会触发观察者吗??
    • 是的,我在操场上测试过。请注意,Path 是一个结构。如果它是一个类,我不会被触发。
    • 完全正确。类不会在依赖链上传播突变。
    • 毕竟,我最终改变了我的架构,我选择了更简单的东西,但是你们给了我一些很棒的想法和我的问题的正确答案。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-30
    • 2016-12-11
    • 2021-11-08
    相关资源
    最近更新 更多