Mvvm SwiftUI:视图模型不更新视图

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"

我尝试用Algolia实现一个搜索栏,并使用MVVM模式

这是我的视图模型:

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()
    }
}

非常感谢基督徒:)很高兴听到它有帮助:)非常感谢基督徒:)很高兴听到它有帮助:)