mvvm - SwiftUI: View 模型不会更新 View

标签 mvvm swiftui full-text-search algolia

我尝试使用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中,ListNewChatView中保持为空。
View 模型内的print(self.idList)语句显示正确的idList,但不会更新List内的NewChatView

最佳答案

首先,您需要创建自己的自定义IdentifiableHashable模型,以searchValueList显示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/

相关文章:

c# - 替换本地 : keyword with a path? 的适当方法是什么

c# - 如何将网格绑定(bind)到 WPF 中选定的 TreeView 项

SwiftUI - NavigationView 错误消息 - 传递给不带参数的调用的参数

java - Lucene 通过 URL 搜索

C# - WPF 在 DataGridColumnHeader 中使用 DataTrigger

wpf - MVVM 模型验证和数据绑定(bind)?

swiftui - 如何对不同的形状使用相同的修饰符集

ios - SwiftUI 演示模式 : Check if view is presented by sheet

mysql - 如何正确禁用 MariaDB 的 InnoDB 全文停用词?

mysql部分词搜索