Reputation: 1984
Can I implement a protocol partially in Objective C and partially in Swift?
I have an existing Objective C class that's declared like this in the .h file.
@interface SetupViewController : UIViewController <UITableViewDataSource> {
// etc.
}
The corresponding .m file implements the UITableViewDataSource protocol. Now I want to rewrite some of these methods in a Swift extension. But I was hoping not to have to rewrite all of them in Swift right now. (This is just an example snippet, the actual class is much longer.)
@implementation SetupViewController
// I want to rewrite this method in Swift
/*
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 2;
}
*/
// I don't want to rewrite this method in Swift yet
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// lots of code
}
So I moved one of the methods out of the Objective C file into my extension, like this:
@objc extension SetupViewController {
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// new, more involved code
}
}
but this won't compile. I get an error saying Method 'tableView(_:numberOfRowsInSection:)' with Objective-C selector 'tableView:numberOfRowsInSection:' conflicts with previous declaration with the same Objective-C selector
. But I don't have the numberOfRowsInSection
method in the Objective-C file any more, I took it out.
It seems like merely putting the UITableViewDataSource in the .h file makes the Swift extension think that there are already methods implemented to fulfill the protocol.
I have also tried declaring the extension as @objc extension SetupViewController: UITableViewDataSource
and removing it from the .h file, but that fails because the extension doesn't implement the protocol by itself.
Upvotes: 6
Views: 404
Reputation: 32782
When building a project that has mixed Swift+Objective-C code, this is a brief summary of what happens:
The error you see occurs at step #2, at this point the compiler sees that the Objective-C class conforms to UITableViewDataSource
, thus it assumes that the Objective-C code implements the tableView(_:numberOfRowsInSection:)
method, thus it sees a conflict since the Swift code also implements the method.
The source of the problem is the fact that you are trying to implement some of the protocol methods in Objective-C, and some in Swift, and this is not possible, you need to either implement all the non-optional methods of the protocol either in Swift, or Objective-C.
If you really want to go this road, a possible solution would be to move the protocol conformance on the Swift side, and declare all the other methods in the Objective-C header as public methods of that class. But this might cause other problems along the way.
Upvotes: 2