SwiftUI使用EnvironmentObject订阅属性更改

时间:2020-07-22 21:06:06

标签: swift swiftui environmentobject

这是我的模特:

class Channel: Identifiable, Decodable, ObservableObject {
    
    var id = UUID()
    var channelId = ""
    var title = ""
    var thumbnail = ""
    @Published var thumbnailImage : UIImage?
    
    enum CodingKeys: String, CodingKey {
        
        //Keys not in the model
        case snippet
        case thumbnails
        case high
         
        //Keys in the model
        case channelId
        case title
        case thumbnail = "url"
    }
    
    required init (from decoder: Decoder) throws {
        
        let container =  try decoder.container(keyedBy: CodingKeys.self)
        let snippetContainer = try container.nestedContainer(keyedBy: CodingKeys.self, forKey: .snippet)
        let thumbnailsContainer = try snippetContainer.nestedContainer(keyedBy: CodingKeys.self, forKey: .thumbnails)
        let highContainer = try thumbnailsContainer.nestedContainer(keyedBy: CodingKeys.self, forKey: .high)
        
        self.title = try snippetContainer.decode(String.self, forKey: .title)
        self.thumbnail = try highContainer.decode(String.self, forKey: .thumbnail)
        self.channelId = try snippetContainer.decode(String.self, forKey: .channelId)
    }
}
class ChannelStore: ObservableObject {    
    @Published var allChannels = [Channel]()
}

我有一个链接到ChannelStore的EnvironmentObject,并且一切正常。

问题是更改属性thumbnailImage时需要更新我的视图。 (由于来自网络通话,因此视图会在通话返回之前生成,并在此期间使用库存图片)。我尝试将发布的属性包装器添加到该属性,但是它什么也没做。

我认为我有:@EnvironmentObject var channelStore: ChannelStore

如何订阅由EnvironmentObject管理的属性更改?

修改

建议将Channel类更改为结构。我创建类的唯一原因是避免“无法分配给属性:'channel'是'let'常量:

for channel in channelStore.allChannels {
    networking.setThumbnail(channel: channel) { image in
        channel.thumbnailImage = image
    }
}

最终评论

我可以使用下面提供的答案解决整个问题,并将for循环更改为以下内容:

for (index, var channel) in channelStore.allChannels.enumerated() {
    networking.setThumbnail(channel: channel) { image in
        channel.thumbnailImage = image
        channelStore.allChannels[index] = channel
        print("Images LOADED")
    }
}

1 个答案:

答案 0 :(得分:1)

如果您可以将Channel设置为 struct

struct Channel: Identifiable, Decodable { // <- replace `class` with `struct`
    ...
    var thumbnailImage : UIImage? // <- remove `@Published`
}

然后,对thumbnailImage的每次修改都会创建Channel对象的新副本并触发@Published中的ChannelStore属性:

class ChannelStore: ObservableObject {
    @Published var allChannels = [Channel]()
}