为什么在写入可选 属性 时 Combine 分配会崩溃?

Why does Combine assign crash when writing to an optional property?

此代码崩溃(“在展开可选值时意外发现 nil”)

import Combine

class Receiver {
    var value: Int!
    var cancellables = Set<AnyCancellable>([])
    
    init(_ p: AnyPublisher<Int,Never>) {
        p.assign(to: \.value, on: self).store(in: &cancellables)
    }
}

let receiver = Receiver(Just(5).eraseToAnyPublisher())

如果我使用 p.sink { self.value = [=12=] }.store(in: &cancellables) 而不是分配,它不会崩溃,如果我不为 value-属性 使用可选,它也不会崩溃。

对我来说,这看起来像是 Swift 的构造函数代码中的错误,但也许我忽略了什么?

肯定是Combine的一个bug,它在赋值的时候访问了值。如果您将其更改为常规可选而不是隐式解包(将 ! 更改为 ?),它将正常工作。在大多数情况下,您应该避免隐式解包 Optional,除非它们对于设计约束是绝对必要的。

问题

value 是一个“隐式展开的可选”(因此是一个 Optional),但是你的 AnyPublisherOutputInt -这是 不是 而是 Optional.

解决方案

AnyPublisherOutputInt 更改为 Int?,这样它也将是 Optional。这是应用此修复程序的代码示例:

import Combine

class Receiver {
    var value: Int!
    var cancellables = Set<AnyCancellable>([])
    
    init(_ p: AnyPublisher<Int?, Never>) { // `Output` was changed from `Int` to `Int?` here.
        p.assign(to: \.value, on: self).store(in: &cancellables)
    }
}

let receiver = Receiver(Just(5).eraseToAnyPublisher())