18

Lets assume we have a simple generic class:

class Foo<T> {

}

next add to this class an extension which implements UITableViewDatasoure:

extension Foo: UITableViewDataSource {

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        //Code here
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        //Code here
    }
}

This construction causes a compiler error with message:

@objc is not supported within extensions of generic classes or classes that inherit from generic classes Non-'@objc' method

'tableView(_:numberOfRowsInSection:)' does not satisfy requirement of '@objc' protocol 'UITableViewDataSource'

Anyone can tell me why? And how to fix that?

Kamil Harasimowicz
  • 4,684
  • 5
  • 32
  • 58
  • 2
    The error message seems very clear. This isn't supported. You can't attach an `@objc` method to a generic class in an extension. You need to define these methods in the class definition, not an extension. The "why" is "the compiler doesn't support it today." (It's likely hard to support because of specializations, but the real answer is "the compiler can't do it.") – Rob Napier Jan 22 '18 at 17:01
  • Could you provide a more specific example of where you would like to use this? I've been trying to make your example work as it is, but it doesn't look like you can go around this error in any way, with the goal set like this. – Maroš Beťko Jan 22 '18 at 18:20
  • 1
    Tnx @RobNapier. Moving implementation of `UITableViewDataSource` from extension to class definition fixes compiler errors. Also tnx for explanation. I would mark it as answered it would be a possibility. – Kamil Harasimowicz Jan 23 '18 at 09:30
  • @MarošBeťko I've had several cases where I've wanted this, generally for organizational reasons. I like to move protocol implementations into their own extensions; it makes it clearer which methods apply to the extension. I don't think I've encountered a case of this personally where it was strictly necessary, though it would be if `Foo` were defined in another module (such as a third-party framework). – Rob Napier Jan 23 '18 at 13:42
  • @RobNapier I've played around with this for a while and tried many different approaches on how to get around this error, but nothing was reaching the general solution we are looking for here. – Maroš Beťko Jan 23 '18 at 13:50

2 Answers2

41

The error message seems very clear. This isn't supported. You can't attach an @objc method to a generic class in an extension. You need to define these methods in the class definition, not an extension. The "why" is "the compiler doesn't support it today." (It's likely hard to support because of specializations, but the real answer is "the compiler can't do it.")

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
1

Currently the Xcode doesn't support attach an @objc method to a generic class in an extension, you can fix it by define the method inside the class definition, as following:

class Foo<T>: UIViewController, UITableViewDataSource {

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        //Code here ...
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        //Code here ...
    }
}
HanleyLee
  • 61
  • 2