已发布的属性未在 SwiftUI 中更新
Posted
技术标签:
【中文标题】已发布的属性未在 SwiftUI 中更新【英文标题】:Published property not updating in SwiftUI 【发布时间】:2021-12-31 22:14:45 【问题描述】:我有以下代码,我希望 Published 属性标签的更新会反映在 UI 中,但事实并非如此。
public class ViewSearch
@ObservedObject var viewModel: ViewModel
/// Main initializer for instance.
/// - Parameter viewModel: The view model for searching.
public init(viewModel: ViewModel)
self.viewModel = viewModel
func doSomething()
for i in 1...1000000
if i % 250000 == 0
viewModel.label = "value: \(i)"
viewModel.label = "Done!"
public class ViewModel: ObservableObject
@Published public var label = "initial value"
didSet
print("\(label)")
self.objectWillChange.send()
@Published public var searchText = ""
var search: ViewSearch? = nil
struct ContentView: View
@ObservedObject var model: ViewModel
var body: some View
TextField("Search", text: $model.searchText) isEditing in
if isEditing
model.label = "initial value"
onCommit:
if !model.searchText.isEmpty
model.search = ViewSearch(viewModel: model)
model.search?.doSomething()
Text(model.label)
在提交文本字段输入时触发更新。我希望 UI 显示“值:250000”、“值:500000”等。 didSet 观察者显示更改但 UI 未更新。为什么不呢?
【问题讨论】:
【参考方案1】:for 循环将阻塞主队列,因此创建一个队列以在另一个线程上运行 for i in 1...1000000
//
// ContentView.swift
// ***
//
// Created by Mustafa T Mohammed on 12/31/21.
//
import SwiftUI
public class ViewSearch
@ObservedObject var viewModel: ViewModel
/// Main initializer for instance.
/// - Parameter viewModel: The view model for searching.
public init(viewModel: ViewModel)
self.viewModel = viewModel
func doSomething()
let q = DispatchQueue.init(label: "doSomething")
// for loop will block the main queue so create a queue to run for i in 1...1000000
// on another thread
q.async [weak self] in // weak self to prevent retain cycle
guard let self = self else return
for i in 1...1000000
if i % 250000 == 0
DispatchQueue.main.async //update UI by coming back to main thread
self.viewModel.label = "value: \(i)"
DispatchQueue.main.async //update UI by coming back to main thread
self.viewModel.label = "Done!"
public class ViewModel: ObservableObject
@Published public var label = "initial value"
didSet
print("\(label)")
self.objectWillChange.send()
@Published public var searchText = ""
var search: ViewSearch? = nil
struct ContentView: View
@ObservedObject var model: ViewModel
var body: some View
TextField("Search", text: $model.searchText) isEditing in
if isEditing
model.label = "initial value"
onCommit:
if !model.searchText.isEmpty
model.search = ViewSearch(viewModel: model)
model.search?.doSomething()
Text(model.label)
【讨论】:
很好......我已经尝试了 DispatchQueue.main,但如果 for 循环仍在主队列上运行,我想我对 DispatchQueue.main 的使用什么也没做。以上是关于已发布的属性未在 SwiftUI 中更新的主要内容,如果未能解决你的问题,请参考以下文章
已发布值上的 SwiftUI toggle() 函数停止使用 Swift 5.2 触发 didSet