我知道,这是“无法在 iOS XX 中工作”问题之一,但我完全陷入困境......
所以我有一个ObservableObject
继承自的类NSObject
,因为我需要听委托方法UISearchResultsUpdating
.
class SearchBarListener: NSObject, UISearchResultsUpdating, ObservableObject {
@Published var searchText: String = ""
let searchController: UISearchController = UISearchController(searchResultsController: nil)
override init() {
super.init()
self.searchController.searchResultsUpdater = self
}
func updateSearchResults(for searchController: UISearchController) {
/// Publish search bar text changes
if let searchBarText = searchController.searchBar.text {
print("text: \(searchBarText)")
self.searchText = searchBarText
}
}
}
struct ContentView: View {
@ObservedObject var searchBar = SearchBarListener()
var body: some View {
Text("Search text: \(searchBar.searchText)")
.padding()
/// more code that's not related
}
}
问题是,即使print("text: \(searchBarText)")
打印效果很好,Text("Search text: \(searchBar.searchText)")
从未更新过(在 iOS 13 中)。在 iOS 14 中运行良好。
这是一个最小的可重现示例:
class SearchBarTester: NSObject, ObservableObject {
@Published var searchText: String = ""
override init() {
super.init()
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
print("updated")
self.searchText = "Updated"
}
}
}
struct ContentView: View {
@ObservedObject var searchBar = SearchBarTester()
var body: some View {
NavigationView {
Text("Search text: \(searchBar.searchText)")
.padding()
}
}
}
5秒后,控制台打印出“updated”,但是Text
没有改变。在 iOS 14 中,Text
更改为“搜索文本:已更新”正如预期的那样。
但是,如果我不继承NSObject
, bothiOS 13 和 iOS 14 可以使用!
class SearchBarTester: ObservableObject {
@Published var searchText: String = ""
init() {
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
print("updated")
self.searchText = "Updated"
}
}
}
我认为这个问题与从类继承有关。也许这是 iOS 14 中修复的问题。但是有人知道发生了什么吗?
Edit
Thanks @Cuneyt https://stackoverflow.com/users/2739567/为了答案!这是最终起作用的代码:
import SwiftUI
import Combine /// make sure to import this
class SearchBarTester: NSObject, ObservableObject {
let objectWillChange = PassthroughSubject<Void, Never>()
@Published var searchText: String = "" {
willSet {
self.objectWillChange.send()
}
}
override init() {
super.init()
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
print("updated")
self.searchText = "Updated"
}
}
}