Asynchronous 如何链接可观察对象?
我有一个可以保存图像的游戏对象。每当为游戏找到图像URL时,都应创建GameImage对象的新实例。然后,它将获取图像并填充UIImage属性。发生这种情况时,应更新显示图像的UIAsynchronous 如何链接可观察对象?,asynchronous,swiftui,combine,Asynchronous,Swiftui,Combine,我有一个可以保存图像的游戏对象。每当为游戏找到图像URL时,都应创建GameImage对象的新实例。然后,它将获取图像并填充UIImage属性。发生这种情况时,应更新显示图像的UI class Game: ObservableObject { @Published var image: GameImage? } class GameImage: ObservableObject { let url: URL @Published var image: UIImage?
class Game: ObservableObject {
@Published var image: GameImage?
}
class GameImage: ObservableObject {
let url: URL
@Published var image: UIImage?
private var cancellable: AnyCancellable?
init(url: URL) {
self.url = url
}
func fetch() {
self.cancellable = URLSession.shared.dataTaskPublisher(for: self.url)
.map { UIImage(data: $0.data) }
.replaceError(with: nil)
.receive(on: DispatchQueue.main)
.sink(receiveValue: { [weak self] (image) in
guard let self = self else { return }
self.image = image
print(self.url)
print(self.image)
})
}
func cancel() {
cancellable?.cancel()
}
deinit {
cancel()
}
}
struct ContentView: View {
@StateObject var game = Game()
var body: some View {
VStack {
if let image = game.image?.image {
Image(uiImage: image)
} else {
Text("No image.")
}
}
.onAppear(perform: {
guard let gameImageURL = URL(string: "https://cf.geekdo-images.com/itemrep/img/oVEpcbtyWkJjIjk1peTJo6hI1yk=/fit-in/246x300/pic4884996.jpg") else { return }
game.image = GameImage(url: gameImageURL)
game.image!.fetch()
})
}
}
问题是。获取完成后,调试控制台将显示映像包含UIImage。但是,UI不会更新以显示图像。这里我缺少了什么?有比链接
可观察对象更简单的解决方案,只需将依赖部分分离到独立的子视图中。。。所有这些都将自动工作
以下是可能的方法。使用Xcode 12/iOS 14进行测试
struct ContentView: View {
@StateObject var game = Game()
var body: some View {
VStack {
if nil != game.image {
GameImageView(vm: game.image!)
}
}
.onAppear(perform: {
guard let gameImageURL = URL(string: "https://cf.geekdo-images.com/itemrep/img/oVEpcbtyWkJjIjk1peTJo6hI1yk=/fit-in/246x300/pic4884996.jpg") else { return }
game.image = GameImage(url: gameImageURL)
game.image!.fetch()
})
}
}
struct GameImageView: View {
@ObservedObject var vm: GameImage
var body: some View {
if let image = vm.image {
Image(uiImage: image)
} else {
Text("No image.")
}
}
}
你会显示依赖于这个视图模型的UI吗?我不知道你的意思。游戏实例Game
应包含真理的单一来源。游戏对象还可以包含其他属性,如名称,我从这个示例中删除了这些属性,以避免使事情过于复杂。无论何时图像可用,它都应该显示它,这样它是依赖的。不强制展开选项不是更好吗?难道不是游戏.image?.fetch()
?我知道这是一个问题,但你总是可以改进它。是的,虽然在这个例子中我把game.image设置在上面一行,所以它非常安全。我刚刚测试了代码,它工作了。“我仍在试图理解这个概念。@当然可以,但作为一种良好的做法,我建议不要强制展开选项。以后你可以把这一行复制到别的地方,然后忘掉它。