Мое приложение имеет общий базовый класс для всех контроллеров таблиц, и я испытываю странную ошибку, когда я определяю общий подкласс этого базового класса контроллера. Метод numberOfSections(in:) никогда не вызывается в том и только в том случае, если мой подкласс является общим.
Ниже представлено самое маленькое воспроизведение, которое я мог бы сделать:
class BaseTableViewController: UIViewController {
  let tableView: UITableView
  init(style: UITableViewStyle) {
    self.tableView = UITableView(frame: .zero, style: style)
    super.init(nibName: nil, bundle: nil)
  }
  required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }
  // MARK: - Overridden methods
  override func viewDidLoad() {
    super. viewDidLoad()
    self.tableView.frame = self.view.bounds
    self.tableView.delegate = self
    self.tableView.dataSource = self
    self.view.addSubview(self.tableView)
  }
}
extension BaseTableViewController: UITableViewDataSource {
  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 0
  }
  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    return UITableViewCell(style: .default, reuseIdentifier: nil)
  }
}
extension BaseTableViewController: UITableViewDelegate {
}
Здесь очень простой общий подкласс:
class ViewController<X>: BaseTableViewController {
  let data: X
  init(data: X) {
    self.data = data
    super.init(style: .grouped)
  }
  required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }
  func numberOfSections(in tableView: UITableView) -> Int {
    // THIS IS NEVER CALLED!
    print("called numberOfSections")
    return 1
  }
  override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    print("called numberOfRows for section \(section)")
    return 2
  }
  override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    print("cellFor: (\(indexPath.section), \(indexPath.row))")
    let cell = UITableViewCell(style: .default, reuseIdentifier: nil)
    cell.textLabel!.text = "foo \(indexPath.row) \(String(describing: self.data))"
    return cell
  }
  func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    print("didSelect: (\(indexPath.section), \(indexPath.row))")
    self.tableView.deselectRow(at: indexPath, animated: true)
  }
}
Если я создаю простое приложение, которое ничего не делает, кроме отображения ViewController:
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
  var window: UIWindow?
  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    self.window = UIWindow(frame: UIScreen.main.bounds)
    let nav = UINavigationController(rootViewController: ViewController(data: 3))
    self.window?.rootViewController = nav
    self.window?.makeKeyAndVisible()
    return true
  }
}
Таблица рисуется правильно, но numberOfSections(in:) никогда не вызывается! В результате таблица показывает только один раздел (предположительно потому, что, согласно документам, UITableView использует 1 для этого значения, если метод не реализован).
Однако, если я удалю общее объявление из класса:
class ViewController: CustomTableViewController {
  let data: Int
  init(data: Int) {
  ....
  }
  // ...
}
 тогда numberOfSections Звонит!
Такое поведение не имеет для меня никакого смысла. Я могу обойти это, определив numberOfSections в CustomTableViewController, а затем ViewController явно переопределит эту функцию, но это не похоже на правильное решение: я должен был бы сделать это для любого метода в UITableViewDataSource, который имеет эту проблему.
