#ios #swift #generics #protocol-oriented
#iOS #swift #дженерики #ориентированный на протокол
Вопрос:
Я хочу, чтобы свойство «cellViewModel» было общим, чтобы я мог повторно использовать BaseCustomCell с различными типами моделей. Например.
struct CELLVIEWMODEL {
var name: String
var address: String
}
class BaseCustomCell: UITableViewCell {
var cellViewModel: CELLVIEWMODEL //should support different model types CELLVIEWMODEL1,CELLVIEWMODEL2
{
didSet() {
setValuesInSubClasses
}
}
func setValuesInSubClasses() {
//subclass will implement
}
}
class subCell: BaseCustomCell {
override func setValuesInSubClasses() {
//set value from cellViewModel
}
}
// Вот как я настраиваю из метода cellForRowAtIndexPath:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: viewModel.getCellId(), for: indexPath) as! BaseCustomCell
cell.cellViewModel = viewModel.getCellModelAtIndexPath(indexPath) //this will set values for subclasses
return cell
}
Теперь я каждый раз создаю новую BaseCustomCell для разных типов cellViewModel. Не могли бы вы помочь с каким-либо решением?
Ответ №1:
Существует несколько способов достижения ваших целей.
Вы можете сделать фактический BaseCustomCell
glass универсальным, но имейте в виду, что если вы используете раскадровки, это не решение, поскольку вам нужно будет жестко закодировать общий тип в раскадровке.
Другое решение, которое также работает с раскадровками, — объявить вашу viewmodel как протокол, затем вы можете заменить его любой конкретной реализацией протокола.
protocol CellViewModel {
var name: String { get }
var address: String { get }
}
class BaseCustomCell: UITableViewCell {
var cellViewModel: CellViewModel {
didSet() {
setValuesInSubClasses
}
}
func setValuesInSubClasses() {
//subclass will implement
}
}
class SubCell: BaseCustomCell {
override func setValuesInSubClasses() {
//set value from cellViewModel
}
}
И тогда у вас viewModel.getCellModelAtIndexPath
должен быть возвращаемый тип CellViewModel
, чтобы он мог возвращать любой тип, соответствующий протоколу.
Итак, вам просто нужно объявить ваши конкретные модели представления ячеек, например class FirstCellViewModel: CellViewModel { ... }
, и т. Д., И Вы можете вернуть их из getCellModelAtIndexPath
Комментарии:
1. Я не использую раскадровку. Для меня это выглядит хорошо, можете ли вы добавить еще несколько объяснений, пожалуйста.
2. @AvijitNagare не уверен, что еще я могу объяснить, не вдаваясь в более конкретную проблему. Как я уже сказал, просто объявите тип
cellViewModel
в качестве протокола,viewModel.getCellModelAtIndexPath
укажите возвращаемый тип протокола, затем внутри реализацииgetCellModelAtIndexPath
вы можете возвращать конкретные типы моделей представления в зависимости от того, какие у вас есть критерии.3. Не удалось установить значения для типа протокола CellViewModel в подклассе, поскольку я объявил CellViewModel(базовый протокол) со свойствами not. но у моего подкласса есть свойства, и мне необходимо обновить cellViewModel(чьи свойства не совпадают с базовыми cellViewModel). любое решение для этого.
4. @AvijitNagare просто приведите
cellViewModel
к конкретному типу, используяcellViewModel as? YourType