我尝试使用Algolia实现搜索栏,并且使用MVVM模式。
这是我的 View 模型:
class AlgoliaViewModel: ObservableObject {
@Published var idList = [String]()
func searchUser(text: String){
let client = SearchClient(appID: "XXX", apiKey: "XXX")
let index = client.index(withName: "Users")
let query = Query(text)
index.search(query: query) { result in
if case .success(let response) = result {
print("Response: \(response)")
do {
let hits: Array = response.hits
var idList = [String]()
for x in hits {
idList.append(x.objectID.rawValue)
}
DispatchQueue.main.async {
self.idList = idList
print(self.idList)
}
}
catch {
print("JSONSerialization error:", error)
}
}
}
}
}
这是我的观点:struct NewChatView : View {
@State private var searchText = ""
@ObservedObject var viewModel = AlgoliaViewModel()
var body : some View{
VStack(alignment: .leading){
Text("Select To Chat").font(.title).foregroundColor(Color.black.opacity(0.5))
ScrollView(.vertical, showsIndicators: false) {
VStack(spacing: 12){
HStack {
TextField("Start typing",
text: $searchText,
onCommit: { self.viewModel.searchUser(text: self.searchText) })
.textFieldStyle(RoundedBorderTextFieldStyle())
Button(action: {
self.viewModel.searchUser(text: self.searchText)
}) {
Image(systemName: "magnifyingglass")
}
} .padding()
List {
ForEach(viewModel.idList, id: \.self){ i in
Text(i)
}
}
}
}
}.padding()
}
}
我经常在Firebase中使用此模式,并且一切正常,但是在Algolia中,List
在NewChatView
中保持为空。View 模型内的
print(self.idList)
语句显示正确的idList
,但不会更新List
内的NewChatView
。
最佳答案
首先,您需要创建自己的自定义Identifiable
和Hashable
模型,以searchValue
或List
显示ForEach
。
像这样:
struct MySearchModel: Identifiable, Hashable {
let id = UUID().uuidString
let searchValue: String
}
然后在AlgoliaViewModel
中使用它。设置一个空数组的默认值。您还可以映射收到的
hits
并将其转换为新模型。不需要额外的for
循环。class AlgoliaViewModel: ObservableObject {
@Published var idList: [MySearchModel] = []
func searchUser(text: String) {
let client = SearchClient(appID: "XXX", apiKey: "XXX")
let index = client.index(withName: "Users")
let query = Query(text)
index.search(query: query) { result in
if case .success(let response) = result {
print("Response: \(response)")
do {
let hits: Array = response.hits
DispatchQueue.main.async {
self.idList = hits.map({ MySearchModel(searchValue: $0.objectID.rawValue) })
print(self.idList)
}
}
catch {
print("JSONSerialization error:", error)
}
}
}
}
}
对于NewChatView
,您可以删除ScrollView
,因为它与当前VStack
中的元素冲突,并且也会隐藏List
和结果。以下更改应显示所有结果。struct NewChatView : View {
@State private var searchText = ""
@ObservedObject var viewModel = AlgoliaViewModel()
var body: some View{
VStack(alignment: .leading) {
Text("Select To Chat")
.font(.title)
.foregroundColor(Color.black.opacity(0.5))
VStack {
HStack {
TextField("Start typing",
text: $searchText,
onCommit: { self.viewModel.searchUser(text: self.searchText)
})
.textFieldStyle(RoundedBorderTextFieldStyle())
Button(action: {
self.viewModel.searchUser(text: self.searchText)
}) {
Image(systemName: "magnifyingglass")
}
} .padding()
List {
ForEach(viewModel.idList) { i in
Text(i.searchValue)
.foregroundColor(Color.black)
}
}
}
}.padding()
}
}
关于mvvm - SwiftUI: View 模型不会更新 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63525054/