Я разработал свой поисковый компонент на основе этого учебника .
. Он хорошо работает, если у меня есть один раздел в табличном представлении, поэтому мне не нужно беспокоиться о вложенных вещах..
Вот мой код:
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 = $0.query.range(of: query, options: NSString.CompareOptions.caseInsensitive)
return (queryToFind != nil)
}
}
}
У меня есть реализация этого класса, соответствующая указанному протоколу:
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
}
}
Так что теперь, когда я использую свой подкласс:parent BaseSearchDataSource Я могу просто указать класс, который я хочу загрузить в мое табличное представление, и сделать этот класс доступным для поиска.Так что теперь мой var models: [T]
представляет модели как [MuscleSelectableItem]
Я понимаю, что мне нужно использовать некоторый объект раздела с вложенными элементами вроде:
class TableViewSection {
var items: [MuscleSelectableItem]
}
Но проблема с кодом вышеЯ указал конкретный тип [MuscleSelectableItem]
для items
.
Как объявить [T]
, который будет TableViewSection
с items
, которые не определены, пока мы не сообщим компилятору в подклассах, какой тип мы хотим использоватьдля items
, например для поиска городов, мышц или книг или любых других объектов, поэтому items
может быть любым из них
Также мне не нравится, что мой протокол содержит функции поиска и выборакак правильно его отделить?