为了简单起见,我修改了我的项目并创建了可重现的代码。
考虑我有以下Item
数据结构:
struct Item: Identifiable {
let id = UUID()
let isChecked: AnyPublisher<Bool, Never>
let name: String
}
当该值发布任何新值时,我ItemCell
应该更新以下内容。isChecked
struct ItemCell: View {
var item: Item
@State var imgState: Bool = false
var cancellables = Set<AnyCancellable>()
init(_ item: Item) {
self.item = item
item.isChecked
.print("State for item \(item.name): ") // --> Check this print
.assign(to: \.imgState, on: self)
.store(in: &cancellables)
}
var body: some View {
HStack {
HStack {
Image(systemName: imgState ? "checkmark.circle.fill" : "checkmark.circle")
.foregroundStyle(.blue)
Text(item.name)
}
}
}
}
我已在调试控制台中检查到isChecked
始终发出值,但视图未更新。
无论如何,要测试我创建的虚拟代码,您只需复制并粘贴即可进行测试:
完整代码:
import SwiftUI
import Combine
struct Item: Identifiable {
let id = UUID()
let isChecked: AnyPublisher<Bool, Never>
let name: String
}
struct ItemCell: View {
var item: Item
@State var imgState: Bool = false
var cancellables = Set<AnyCancellable>()
init(_ item: Item) {
self.item = item
item.isChecked
.print("State for item \(item.name): ")
.assign(to: \.imgState, on: self)
.store(in: &cancellables)
}
var body: some View {
HStack {
HStack {
Image(systemName: imgState ? "checkmark.circle.fill" : "checkmark.circle")
.foregroundStyle(.blue)
Text(item.name)
}
}
}
}
struct ContentView: View {
var viewModel = ContentViewModel()
var body: some View {
List(viewModel.items) { item in
ItemCell(item)
}
}
}
class ContentViewModel: ObservableObject {
var itemNames = ["A", "B", "C", "D"]
@Published var checkList = [false, false, false, false]
init() {
updateChecklist()
}
// Dummy function to update data
func updateChecklist() {
Timer.scheduledTimer(withTimeInterval: 2, repeats: true) { [weak self] _ in
for index in 0...3 {
self?.checkList[index] = Bool.random()
}
}
}
// Dummy items whose isChecked data are continuously updating with publisher
var items: [Item] {
(0...3).map { index in
Item(
isChecked: $checkList
.map { $0[index] == true }
.eraseToAnyPublisher(),
name: itemNames[index]
)
}
}
}
#Preview {
ContentView()
}
我预计当isChecked
发布者发出值时,SwiftUI 视图ItemCell
也应该更新。但它没有更新。
一般来说,您应该用来
onReceive
监听发布者发布的值:这对于您的玩具示例来说是正确的。
远离您人为的示例,假设发布的值来自某个外部源,而不是属性
@Published
(这是非常人为的)。您@Published
的.[Item]
要分配给此数组中的 s 的发布者。ContentViewModel
sink
Item
然后
ItemView
不需要任何代码来观察变化。ContentView
观察ContentViewModel.items
,并自动传播更改。在 iOS 17+ 上,您可以创建
Item
一个@Observable class
,并让每个项目管理自己的发布者:这实际上对 s 不起作用,
ObservableObject
因为 SwiftUI 无法观察ObservableObject
已放入数组中的 s 的更改。