Swift ReferenceWritableKeyPath如何与Optional属性一起使用?

问题描述 投票:6回答:1

Ground of Being:这将有助于在阅读之前了解您无法通过键路径image将UIImage分配给图像视图插座的\UIImageView.image属性。这是属性:

@IBOutlet weak var iv: UIImageView!

现在,可以编译吗?

    let im = UIImage()
    let kp = \UIImageView.image
    self.iv[keyPath:kp] = im // error

不!

可选类型'UIImage的值?必须解压为'UIImage'类型的值]

好,现在我们可以开始实际使用了。


我实际上想了解的是Combine框架.assign订户在后台如何工作。为了进行实验,我尝试使用自己的Assign对象。在我的示例中,我的发布者管道生成一个UIImage对象,并将其分配给UIImageView属性imageself.iv属性。

如果使用.assign方法,则可以编译并运行:

URLSession.shared.dataTaskPublisher(for: url)
    .map {$0.data}
    .replaceError(with: Data())
    .compactMap { UIImage(data:$0) }
    .receive(on: DispatchQueue.main)
    .assign(to: \.image, on: self.iv)
    .store(in:&self.storage)

因此,我对自己说,要了解其工作原理,我将删除.assign并将其替换为我自己的Assign对象:

let pub = URLSession.shared.dataTaskPublisher(for: url)
    .map {$0.data}
    .replaceError(with: Data())
    .compactMap { UIImage(data:$0) }
    .receive(on: DispatchQueue.main)

let assign = Subscribers.Assign(object: self.iv, keyPath: \UIImageView.image)
pub.subscribe(assign) // error
// (and we will then wrap in AnyCancellable and store)

拍手!我们不能这样做,因为UIImageView.image是一个可选的UIImage,而我的发布者生成的UIImage简单明了。

我试图通过在密钥路径中展开Optional来解决此问题:

let assign = Subscribers.Assign(object: self.iv, keyPath: \UIImageView.image!)
pub.subscribe(assign)

很酷,可以编译。但是它在运行时崩溃,可能是因为图像视图的图像最初是nil

现在,我可以通过在管道中添加map来解决所有这些问题,该管道将UIImage包裹在Optional中,以便所有类型都正确匹配。但是我的问题是,这really

如何工作?我的意思是,为什么我不必在使用.assign的第一个代码中这样做?为什么我可以在那里指定.image键路径?关键路径如何与Optional属性一起使用似乎有些技巧,但我不知道它是什么。

[从Martin R输入一些信息后,我意识到,如果在生成pub时显式键入UIImage?,我们将获得与添加map并将UIImage包装在Optional中的效果相同的效果。这样就可以编译工作了

let pub : AnyPublisher<UIImage?,Never> = URLSession.shared.dataTaskPublisher(for: url)
    .map {$0.data}
    .replaceError(with: Data())
    .compactMap { UIImage(data:$0) }
    .receive(on: DispatchQueue.main)
    .eraseToAnyPublisher()

let assign = Subscribers.Assign(object: self.iv, keyPath: \UIImageView.image)
pub.subscribe(assign)
let any = AnyCancellable(assign)
any.store(in:&self.storage)

这仍然不能解释原始.assign的工作原理。看来,可以将类型up

的可选性push
传递到.receive运算符中。但是我不知道怎么可能。

存在的基础:在阅读之前,这将有助于您不能通过键路径\ UIImageView.image将UIImage分配给图像视图插座的image属性。这是属性:@IBOutlet ...

swift optional combine swift-keypath
1个回答
0
投票

我不会回答这个问题:

这仍然不能解释原始.assign的工作原理。

© www.soinside.com 2019 - 2024. All rights reserved.