已发布 属性 未在 SwiftUI 中更新
Published property not updating in SwiftUI
我有以下代码,我希望对 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 未更新。为什么不呢?
for 循环将阻塞主队列,因此在另一个线程
上创建一个队列 运行 for i in 1...1000000
//
// ContentView.swift
// Whosebug
//
// 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)
}
}
我有以下代码,我希望对 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 未更新。为什么不呢?
for 循环将阻塞主队列,因此在另一个线程
上创建一个队列 运行 for i in 1...1000000 //
// ContentView.swift
// Whosebug
//
// 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)
}
}