更新 属性 没有 运行 组合管道

Update property without running combine pipeline

如果我有一个组合管道,它打印对数组的更改,那么是否可以在没有管道的情况下更新该数组运行?

class ObserveableTest: ObservableObject {
    private var cancellables: Set<AnyCancellable> = []
    @Published var items: [Int] = []
    init() {
        $items
            .debounce(for: 0.6, scheduler: RunLoop.main)
            .sink {
                print([=12=])
            }
            .store(in: &cancellables)
    }
    
    func pleaseDoNotNotifyPipeline() {
        items.append(1)
    }
}

更新: 提供的代码是我所做工作的简化版本。 简而言之,我在购物篮管理器上工作,每当用户更改产品数量(或以其他方式更改购物篮)时,都需要向后端发送请求,为什么会出现反跳。在上面的代码中,它只是通过对数组的更改来显示。

情况是,用户对购物篮所做的更改应该 运行 管道,但是,也可能是系统(通过网络响应等)更新了本地购物篮本身,在这种情况下,管道不应 运行.

我担心在极少数情况下取消和重新订阅管道可能意味着用户所做的更改丢失。 但我也可能意识到 cancel/resub 是唯一的解决方案,我需要处理这种罕见的情况。或者你看到我已经详细说明的其他解决方案了吗?

我不知道 Combine 中的 pause 功能。您指向订阅的指针是返回的 AnyCancellable.

您添加了 debounce。我很好奇你是否想忽略第一个值(在你的例子中是一个空数组)。为此,您可以在管道中使用 .dropFirst()

否则,我认为您必须取消并重新订阅才能更改 items

class Test: ObservableObject {
    private var cancellable: AnyCancellable?
    @Published var items: [Int] = []
    init() {
       observe()
    }
    
    func pleaseDoNotNotifyPipeline() {
        cancel()
        items.append(1)
        observe()
    }
    
    func cancel() {
        cancellable?.cancel()
    }
    
    func observe() {
        cancellable = $items
            .dropFirst() // ignores the first value []
            .sink {
                print([=10=])
            }
    }
}

经过进一步检查,我得到了答案。 class PassthroughSubject.

就是这种情况
class ObserveableTest: ObservableObject {
    
    private var cancellables: Set<AnyCancellable> = []

    /// private(set) to restrict all changes to go through class functions
    @Published private(set) var items: [Int] = []

    /// A subject we can pass data into, when we wanna publish changes
    private let listener = PassthroughSubject<[Int], Never>()
    
    init() {
        listener
            .debounce(for: 0.6, scheduler: RunLoop.main)
            .sink {
                print([=10=])
            }
            .store(in: &cancellables)
    }
    

    func thisFunctionIsCalledByUserAndTriggersPipeline() {
        items.append((0...1000000).randomElement()!)
        listener.send(items) // publish to pipeline
    }
    
    func thisFunctionIsCalledByServerAndDoesNotTriggerPipeline() {
        items.append((0...1000000).randomElement()!)
    }
    
}

这是一个自古以来的问题 :) 如果请求与前一个请求相同,如何避免发出服务器请求?

removeDuplicates():

init() {
    $items
        .debounce(for: 0.6, scheduler: RunLoop.main)
        .removeDuplicates()
        .sink {
            print([=10=])
        }
        .store(in: &cancellables)
}

这假设您的数据对象是一个 Equatable 对象,但如果还没有的话,应该不难制作。