Предоставление реализации по умолчанию для переопределенного метода UIViewController, но только если контроллер соответствует протоколу
В моем приложении у меня было много стандартного кода, который мне приходилось писать всякий раз, когда в каком-то контроллере был UITableView. Чтобы устранить это, я создал BaseTableViewController, который реализует некоторые неоднократно используемые UITableDataSource
такие операции, как tableView(_:numberOfRowsInSection:)
а также tableView(_:cellForRowAt:)
, В tableView(_:numberOfRowsInSection:)
, мой BaseTableViewController извлекает фактическое количество строк в разделе из другого метода (давайте назовем его rowCount(inSection:)
) и выполняет некоторые вычисления, используя его, затем возвращает результат делегирующему вызывающему. Каждый подкласс класса BaseTableViewController должен переопределить rowCount(inSection:)
метод и возвращает правильное количество строк в данном разделе (сам BaseTableViewController возвращает 0 в своей реализации по умолчанию).
Теперь некоторые из моих контроллеров табличного представления поддерживают разбиение на страницы для отображаемых записей - когда пользователи прокручивают табличное представление до последней строки, следующая партия строк извлекается из сети. Пытаясь сделать вещи более ориентированными на протокол, я создал протокол для постраничных контроллеров:
protocol Pageable: class {
associatedtype DataType
var pages: [[DataType]] { get set } // Each page is an array of elements, hence the table in a table
func loadNextPage()
}
Если контроллер Pageable
, rowCount(inSection:)
методы всегда выглядят так:
override func rowCount(inSection: Int) -> Int {
return self.pages[section].count
}
Это утомительно, потому что каждый потомок BaseTableViewController, который также является Pageable, должен иметь эту точную реализацию, которая нарушает DRY.
Я не могу добавить реализацию по умолчанию в расширении протокола для Pageable
потому что контроллер уже имеет свою собственную реализацию, унаследованную от BaseTableViewController.
Я придумал решение, но мне оно не нравится: я мог бы создать PageableTableViewController (подкласс BaseTableViewController), который обеспечивает собственную переопределенную реализацию rowCount(inSection:)
, но это не очень ориентировано на протокол. Я также пытался переместить rowCount(inSection:)
метод к протоколу, но если я сделаю все потомки BaseTableViewController, чтобы соответствовать этому протоколу с расширением протокола, расширяя Pageable
реализовать метод не будет работать.
Как бы я создал механизм, где все подклассы BaseTableViewController
сможет переопределить rowCount(inSection:)
метод, но когда они Pageable
они разделяют реализацию по умолчанию, которая (возможно) помещена в расширение протокола Pageable?
1 ответ
Вы можете достичь того, что ищете, с помощью расширений протокола. расширение будет применяться только в том случае, если объект, реализующий протокол, на самом деле является UIViewController.
protocol something {
func method()
}
extension something where Self: UIViewController {
func method() {
//Default implementation
}
}