Swift 通过 UITableVIew 中的部分进行通用基本搜索功能
Swift generic base search functionality through section in UITableVIew
我根据这个tutorial设计了我的搜索组件。
如果我在 table 视图中有一个部分,它会很好用,所以我不需要担心嵌套的东西。
这是我的代码:
import UIKit
protocol Searchable {
var query: String { get }
var isSelected: Bool { get set }
}
class BaseSearchDataSource<V, T: Searchable>: NSObject, UITableViewDataSource where V: BaseTableViewCell<T> {
private var models: [T]
private let configureCell: CellConfiguration
typealias CellConfiguration = (V, T) -> V
private var searchResults: [T] = []
private var isSearchActive: Bool = false
init(models: [T], configureCell: @escaping CellConfiguration) {
self.models = models
self.configureCell = configureCell
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return isSearchActive ? searchResults.count : models.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: V = tableView.dequeueReusableCell(forIndexPath: indexPath)
let model = getModelAt(indexPath)
return configureCell(cell, model)
}
func getModelAt(_ indexPath: IndexPath) -> T {
return isSearchActive ? searchResults[indexPath.item] : models[indexPath.item]
}
func search(query: String) {
isSearchActive = !query.isEmpty
searchResults = models.filter {
let queryToFind = [=11=].query.range(of: query, options: NSString.CompareOptions.caseInsensitive)
return (queryToFind != nil)
}
}
}
我有这个 class 实现,它符合指定的协议:
class MuscleSelectableItem: Searchable {
var query: String {
return name
}
var isSelected: Bool
let name: String
let muscle: MusclEntity
init (isSelected: Bool, name: String, muscle: MusclEntity) {
self.isSelected = isSelected
self.name = name
self.muscle = muscle
}
}
所以现在当我使用父 BaseSearchDataSource 的子 class 时,我可以简单地指定一个 class 我想加载到我的 table 视图并制作这个 class可搜索。所以现在我的 var models: [T]
将模型表示为 [MuscleSelectableItem]
我知道我需要使用一些带有嵌套项目的部分对象:
class TableViewSection {
var items: [MuscleSelectableItem]
}
但是我为 items
.
指定了具体类型 [MuscleSelectableItem]
的上面代码的问题
如何声明 [T]
这将是一个 TableViewSection
和 items
直到我们在 subclasses 中告诉编译器我们想要使用什么类型之前是未定义的items
,比如搜索城市、肌肉或书籍或任何其他实体,因此 items
可以是其中任何一个
我也不喜欢我的协议包含搜索和 select 功能,如何正确分离它?
您也可以在包装器中使用泛型。在上面的例子中,它看起来像这样:
class TableViewSection<T> {
var items = [T]()
}
您还可以构建一个 TableDataSource class,它有一个 table 视图部分的数组,这将提供机会,例如基于 indexPath 的下标,然后按顺序使其符合收集协议获得过滤、计数等功能
Also what I don't like as well that my protocol contains search and select functionality, how to separate it correctly?
Swift 允许使用类型别名组合更小协议的协议。以上可以这样划分:
protocol Searchable {
var query: String { get }
}
protocol Selectable {
var isSelected: Bool { get set }
}
typealias SearchAndSelectable = Searchable & Selectable
SearchAndSelectable 类型的变量将同时具有 'query' 和 'isSelected' 值,这对于可以利用两种协议类型的通用约束或函数来说很方便.
我根据这个tutorial设计了我的搜索组件。
如果我在 table 视图中有一个部分,它会很好用,所以我不需要担心嵌套的东西。
这是我的代码:
import UIKit
protocol Searchable {
var query: String { get }
var isSelected: Bool { get set }
}
class BaseSearchDataSource<V, T: Searchable>: NSObject, UITableViewDataSource where V: BaseTableViewCell<T> {
private var models: [T]
private let configureCell: CellConfiguration
typealias CellConfiguration = (V, T) -> V
private var searchResults: [T] = []
private var isSearchActive: Bool = false
init(models: [T], configureCell: @escaping CellConfiguration) {
self.models = models
self.configureCell = configureCell
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return isSearchActive ? searchResults.count : models.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: V = tableView.dequeueReusableCell(forIndexPath: indexPath)
let model = getModelAt(indexPath)
return configureCell(cell, model)
}
func getModelAt(_ indexPath: IndexPath) -> T {
return isSearchActive ? searchResults[indexPath.item] : models[indexPath.item]
}
func search(query: String) {
isSearchActive = !query.isEmpty
searchResults = models.filter {
let queryToFind = [=11=].query.range(of: query, options: NSString.CompareOptions.caseInsensitive)
return (queryToFind != nil)
}
}
}
我有这个 class 实现,它符合指定的协议:
class MuscleSelectableItem: Searchable {
var query: String {
return name
}
var isSelected: Bool
let name: String
let muscle: MusclEntity
init (isSelected: Bool, name: String, muscle: MusclEntity) {
self.isSelected = isSelected
self.name = name
self.muscle = muscle
}
}
所以现在当我使用父 BaseSearchDataSource 的子 class 时,我可以简单地指定一个 class 我想加载到我的 table 视图并制作这个 class可搜索。所以现在我的 var models: [T]
将模型表示为 [MuscleSelectableItem]
我知道我需要使用一些带有嵌套项目的部分对象:
class TableViewSection {
var items: [MuscleSelectableItem]
}
但是我为 items
.
[MuscleSelectableItem]
的上面代码的问题
如何声明 [T]
这将是一个 TableViewSection
和 items
直到我们在 subclasses 中告诉编译器我们想要使用什么类型之前是未定义的items
,比如搜索城市、肌肉或书籍或任何其他实体,因此 items
可以是其中任何一个
我也不喜欢我的协议包含搜索和 select 功能,如何正确分离它?
您也可以在包装器中使用泛型。在上面的例子中,它看起来像这样:
class TableViewSection<T> {
var items = [T]()
}
您还可以构建一个 TableDataSource class,它有一个 table 视图部分的数组,这将提供机会,例如基于 indexPath 的下标,然后按顺序使其符合收集协议获得过滤、计数等功能
Also what I don't like as well that my protocol contains search and select functionality, how to separate it correctly?
Swift 允许使用类型别名组合更小协议的协议。以上可以这样划分:
protocol Searchable {
var query: String { get }
}
protocol Selectable {
var isSelected: Bool { get set }
}
typealias SearchAndSelectable = Searchable & Selectable
SearchAndSelectable 类型的变量将同时具有 'query' 和 'isSelected' 值,这对于可以利用两种协议类型的通用约束或函数来说很方便.