Mvvm SwiftUI:视图模型不更新视图
我尝试用Algolia实现一个搜索栏,并使用MVVM模式 这是我的视图模型:Mvvm SwiftUI:视图模型不更新视图,mvvm,swiftui,full-text-search,algolia,Mvvm,Swiftui,Full Text Search,Algolia,我尝试用Algolia实现一个搜索栏,并使用MVVM模式 这是我的视图模型: class AlgoliaViewModel: ObservableObject { @Published var idList = [String]() func searchUser(text: String){ let client = SearchClient(appID: "XXX", apiKey: "XXX"
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中,列表在新聊天视图中保持为空
视图模型中的print(self.idList)
语句显示右侧的idList
,但是它不会更新新聊天视图中的列表
您首先需要创建自己的自定义可识别
和可散列
模型,以便在列表
或ForEach
中显示搜索值
大概是这样的:
struct MySearchModel: Identifiable, Hashable {
let id = UUID().uuidString
let searchValue: String
}
然后在AlgoliaViewModel
中使用它。设置空数组的默认值。
您还可以映射收到的点击次数
,并将其转换为新型号。对于
循环,不需要额外的
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
中的元素冲突,并且会隐藏带有结果的列表。以下更改应显示所有结果
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()
}
}
首先,您需要创建自己的自定义可识别的和可散列的模型,以便在列表中显示搜索值
,或ForEach
大概是这样的:
struct MySearchModel: Identifiable, Hashable {
let id = UUID().uuidString
let searchValue: String
}
然后在AlgoliaViewModel
中使用它。设置空数组的默认值。
您还可以映射收到的点击次数
,并将其转换为新型号。对于
循环,不需要额外的
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
中的元素冲突,并且会隐藏带有结果的列表。以下更改应显示所有结果
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()
}
}
非常感谢基督徒:)很高兴听到它有帮助:)非常感谢基督徒:)很高兴听到它有帮助:)