使用 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
中使用NSArray
、NSDictionary
,而是使用Array
、Dictionary
。
我已经对你的模型类进行了更改:
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
来检查您必须将哪个数组传递到数据源中过滤的原始数组。在textFieldDidBeginEiditng
和textFieldDidEndEiditng
方法中切换此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<SearchModel>
以上是关于使用 mvvm 搜索 tableview的主要内容,如果未能解决你的问题,请参考以下文章
如何将搜索应用于 MVVM (WPF) 中的列表,而无需每次都调用列表值?
Android MVVM框架使用记事本功能增强:视图类型批量删除搜索笔记