欢迎使用SearchField
开始使用SearchField框架非常简单,但同时它也提供了一种强大的方式来自定义UI。
简单实现
1- 创建一个符合SearchResults
协议的结构体,该结构体应该始终具有一个标题
struct SomeImportantElement: SearchResult {
var title: String = UUID().uuidString
}
2- 符合protocols
将强制您创建以下方法,这些方法是使用SearchField
框架的最低要求
class OurMainViewController: UIViewController, SearchViewControllerDelegate, SearchViewDelegate {}
protocol SearchViewDelegate {
func presentSearchViewController()
}
protocol SearchViewDelegate {
func removeControllerFromView(_ controller: UIViewController)
func selected(searchResult: SearchResult)
}
3- 框架附带一个SearchFieldView
,可以用来展示SearchResult
并打开SearchViewController
,您可以在视图中任何位置将其锚定,并实现SearchViewDelegate
所需的方法。`OurMainViewController`还应实现SearchViewController
所需的方法以选择元素和关闭视图。
动画由FadingAnimation类处理,该类通过实施的淡入淡出效果呈现和关闭SearchViewController
(也可以创建自定义动画并将其发送到transitioningDelegate
)。
private var animation = FadingAnimation()
var someArray = [
SomeImportantElement(),
SomeImportantElement(),
SomeImportantElement(),
]
func presentSearchViewController() {
// Using the Generic Cell for our SomeImportantElement struct and also conforming the SearchView to it too
let controller = SearchViewController<GenericCell<SomeImportantElement>, SomeImportantElement>()
// adding the padding that we want to the results Controller
controller.resultsControllerPadding = .init(top: 10, left: 20, bottom: 10, right: 20)
controller.delegate = self
controller.transitioningDelegate = animation
controller.modalPresentationStyle = .currentContext
controller.searchableElements = someArray
present(controller, animated: true)
}
请注意,过滤是在SearchViewController中完成的,因为我们没有实现以下协议SearchViewControllerDataSource
4- 实现所选方法,并实施一个将控制器从视图中移除的方法以关闭视图
func selected(searchResult: SearchResult) {
// Do something important
print(searchResult)
}
func removeControllerFromView(_ controller: UIViewController) {
controller.dismiss(animated: true)
}
然后您就完成了
5- 如果您想实现自己的DataSource,例如网络调用或一些不需要控制器处理的神奇调用,您可以在`OurMainViewController`中设置数据源代理SearchViewControllerDataSource
private var searchController: SearchViewController<GenericCell<SomeImportantElement>, SomeImportantElement>
func presentSearchViewController() {
/// Code from above
controller.delegate = self
controller.dataSource = self
searchController = controller
/// Code from above
}
现在,由于您可以实现`filter`方法
func filter(text: String?) {
guard let txt = text, !txt.isEmpty else {
// Implement your own way to handle empty Text or might be cool to also implement this with a custom SearchResultsController more on how to do that in Section 2 part 2 of this readme
searchController?.searchableElements = someArray
return
}
// Filtering from someArray or a networking call and setting it to searchableElements
let filtered = someArray.filter { (id) -> Bool in
return id.title.contains(txt)
}
searchController?.searchableElements = filtered
}
一些自定义实现
想要实现一个自定义的单元格,包含一些自定义元素,比如文本、描述以及可能还有图片吗?
1- 例如,现在我们老板想要一个紫色的单元格,但我们真的无法通过当前的实现达到这个效果。这就是我们为什么从创建这个框架开始...
创建一个自定义的结构体来存储你想要的数据
class ClassifiedStruct: SearchResult {
var title: String = UUID().uuidString
var image: UIImage?
var betterTitle: String = "Hello 🐩!"
}
为你要展示的数据创建一个自定义的 GenericCell
class SomeReallyClassifiedImplementation: GenericCell<ClassifiedStruct> {
// <<<HERE COMES YOUR CUSTOM UI IMPLEMENTATION>>>
override var item: Element? {
didSet {
guard let item = item else { return }
superAwesomeTitle.text = betterTitle
poodleImageView.setImage(item.image)
}
}
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
backgroundColor = .purple
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
2- 如果你对我们对 UITableView 的实现不满意,你可以通过继承 SearchResultsController
来实现自己的实现。但是有一些限制,比如你将无法实现分区。你只能实现头部和尾部视图。
class SomeController: SearchResultsController<TestCell, Test> {
override func viewDidLoad() {
super.viewDidLoad()
}
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
// YOU CAN return a custom header
let view = UIView()
view.backgroundColor = .red
return view
}
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
// we return a header in this case when there are zero filtered items
return count == 0 ? 250 : 0
}
}