使用 mvvm 搜索 tableview

Posted

技术标签:

【中文标题】使用 mvvm 搜索 tableview【英文标题】:search the tableview using mvvm 【发布时间】:2018-05-03 04:05:28 【问题描述】:

我需要在 tableview 中搜索。我有 tableview 和 textfield。点击 textfield 时它必须搜索 tableview。

我的模型:-

     class SearchModel: NSObject 


 var restaurantname :String!


    init?(dictionary :JSONDictionary) 

        guard let name = dictionary["name"] as? String  else 
                return
        

        self.restaurantname = name

    




我的视图模型:-

class SearchViewModel: NSObject 


    var datasourceModel:SearchDataSourceModel

    init(withdatasource  newDatasourceModel: SearchDataSourceModel) 
        datasourceModel = newDatasourceModel
    


    func datafordisplay(atindex indexPath: IndexPath) -> SearchModel
        return  datasourceModel.dataListArray![indexPath.row]

    

    func numberOfRowsInSection(section:Int) -> Int 

        return (datasourceModel.dataListArray?.count)!
    




    func loadData(completion :@escaping (_ isSucess:Bool) -> ())


        loadFromWebserviceData  (newDataSourceModel) in

            if(newDataSourceModel != nil)
            




                self.datasourceModel = newDataSourceModel!
                completion(true)

            
            else
                completion(false)
            
        
    


    //
    func loadFromWebserviceData(completion :@escaping (SearchDataSourceModel?) -> ())

        //with using Alamofire  ..............

        Alamofire.request("http://www.example.com").validate(statusCode: 200..<300).validate(contentType: ["application/json"]).responseJSON response in


            switch response.result

            case .success(let data):
                print("success",data)


                let result = response.result
                if     let wholedata = result.value as? [String:Any]


                    if  let data = wholedata["data"] as? Array<[String:Any]>
                        //  print(data["name"] as! String)
                        print(data)
                        print(response)
                        let newDataSource:SearchDataSourceModel = SearchDataSourceModel(array: data)

                        completion(newDataSource)
                        //       
                    
                
                //  case .failure(let data):
                //  print("fail",data)


            case .failure(let encodingError ):
                print(encodingError)


                //  if response.response?.statusCode == 404


                print(encodingError.localizedDescription)

                completion(nil)

                //   
            




        

我的数据源模型:-

class SearchDataSourceModel: NSObject 



    var dataListArray:Array<SearchModel>? = []




    init(array :Array<[String:Any]>?) 
        super.init()
        var newArray:Array<[String:Any]> = []
        if array == nil

         //   newArray = self.getJsonDataStored44()
        
        else
            newArray = array!

        

        var datalist:Array<SearchModel> = []
        for dict in newArray

            let model = SearchModel(dictionary: dict)

            datalist.append(model!)
        
        self.dataListArray = datalist


          




我的视图控制器:-

class SearchViewController: UIViewController,UITableViewDelegate,UITableViewDataSource, UISearchBarDelegate,UITextFieldDelegate 


    @IBOutlet private weak var tableView: UITableView!
  !
    @IBOutlet weak var txt: UITextField!

    var filteredSearchArray = NSMutableArray()



    private var searchViewModel :SearchViewModel!

    init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?, withViewModel viewModel:SearchViewModel) 

        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)

        searchViewModel  = viewModel
    



    required init?(coder aDecoder: NSCoder) 
        fatalError("init(coder:) has not been implemented")
    



    var filteredData: [String]!



    override func viewDidLoad() 
        super.viewDidLoad()




        txt.addTarget(self, action: #selector(textFieldDidChange(textField:)), for: UIControlEvents.editingChanged)



        searchViewModel.loadData  (isSuccess) in


            if(isSuccess == true)
            


                self.tableView .reloadData()


            
            else


                
        



    


    @objc private func textFieldDidChange(textField: UITextField) 
        if textField.text == "" 
           self .viewDidLoad()
        else
            filterContentForSearchText(searchText: textField.text!)
        
    



    func filterContentForSearchText(searchText: String) 
        filteredSearchArray = NSMutableArray(array:(searchViewModel.datasourceModel.dataListArray?.filter((ele:AnyObject) -> Bool in
            return (ele as! SearchModel).restaurantname.lowercased().contains(searchText.lowercased())
        ))!)
        tableView.reloadData()
    


    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return searchViewModel.numberOfRowsInSection(section: section)
    


    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 


        let identifier = "searchcell"
        var cell: SearchCell! = tableView.dequeueReusableCell(withIdentifier: identifier) as? SearchCell

        if cell == nil 
            tableView.register(UINib(nibName: "SearchCell", bundle: nil), forCellReuseIdentifier: identifier)
            cell = tableView.dequeueReusableCell(withIdentifier: identifier) as?SearchCell
        


   cell.setsearchData(search: searchViewModel.datafordisplay(atindex: indexPath))



        return cell
    



我的表格视图单元格:-

class SearchCell: UITableViewCell 




  @IBOutlet weak var name: UILabel!


    override func awakeFromNib() 
        super.awakeFromNib()
        // Initialization code
    

    override func setSelected(_ selected: Bool, animated: Bool) 
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    


    func setsearchData(search:SearchModel)
    
        self.name.text = search.restaurantname


    

这是我的代码,但在 filteredSearchArray 中始终显示为 0 元素。

这里显示的是名称列表,但单击它不搜索且不重新加载的文本字段。如何解决问题。

此代码中没有数据:-

 func filterContentForSearchText(searchText: String) 
        filteredSearchArray = NSMutableArray(array:(searchViewModel.datasourceModel.dataListArray?.filter((ele:AnyObject) -> Bool in
            return (ele as! SearchModel).restaurantname.lowercased().contains(searchText.lowercased())
        ))!)
        tableView.reloadData()
    

【问题讨论】:

所有更改必须在 viewmodel 和 viewcontroller 中做什么才能获得值 能否请您展示您的模型课?以及你是如何定义数组的? @TheTiger 我已经更新了我的代码。请检查。viewmodel 和 viewcontroller 需要进行哪些更改 当您不搜索任何内容时,数据最初是否可见?我的意思是你确定数组包含数据? @TheTiger 最初数据将加载到 tableview 中。 【参考方案1】:

首先有一点很重要,不要在swift 中使用NSArrayNSDictionary,而是使用ArrayDictionary

我已经对你的模型类进行了更改:

class SearchModel: NSObject 
    var restaurantname :String!
    init(dictionary :JSONDictionary) 
        self.restaurantname = dictionary["name"] as? String ?? ""
    

现在像这样过滤你的数组:

filteredSearchArray = searchViewModel.datasourceModel.dataListArray?.filter $0.restaurantname.lowercased().contains(searchText.lowercased())

现在在tableView 数据源中传递filteredSearchArray,然后重新加载表。您可以使用bool 变量isSearching 来检查您必须将哪个数组传递到数据源中过滤的原始数组。在textFieldDidBeginEiditngtextFieldDidEndEiditng 方法中切换此isSearching

我在操场上通过以下示例对其进行了测试:

var models: Array<SearchModel> = [SearchModel.init(dictionary: ["name": "Khalsa Dhaba"]), SearchModel.init(dictionary: ["name": "Yo! China"]), SearchModel.init(dictionary: ["name": "Sher-e-punjab"]), SearchModel.init(dictionary: ["name": "Haveli"])]
let result = models.filter $0.restaurantname.lowercased().contains("o!".lowercased())
print(result)

效果很好! 其次,我注意到您正在通过调用 self.viewDidLoad() 方法重新加载您的视图,您不应该调用它本身,它是 viewContoller 生命周期的函数。请致电tableView.reloadData()

【讨论】:

我不明白如何在我的代码中实现。filteredSearchArray 应该在哪里提供 .is 在视图控制器或模型中。 searchViewModel.numberOfRowsInSection(section: section)cell.setsearchData(search: searchViewModel.datafordisplay(atindex: indexPath)) 您可以在搜索模型中为filteredArray 定义另一个函数和数组,也可以在ViewController 中进行。 if isSearching use fileteredArray else the code you have already @TheTiger 显示错误为:- 无法分配类型 [SearchModel] 的值?输入为 NSMutableArray 不要使用NSMutableArray,只使用Array。定义 filteredSearchArray 与您的原始数组相同,以便 Array&lt;SearchModel&gt;

以上是关于使用 mvvm 搜索 tableview的主要内容,如果未能解决你的问题,请参考以下文章

如何将搜索应用于 MVVM (WPF) 中的列表,而无需每次都调用列表值?

Android MVVM框架使用记事本功能增强:视图类型批量删除搜索笔记

Android MVVM框架使用记事本功能增强:视图类型批量删除搜索笔记

用于搜索屏幕的 MVVM 和 RxSwift

配置更改不保存应用程序状态 MVVM

在MVVM中将SearchBar与ObservableCollection一起使用