Protocol conformance Catch-22

I'm in the process of converting a project to Swift 3, and I've run into a weird conflict with the automatic renaming of Objective-C methods into Swift.

  • I have a Objective-C protocol Foo that declares a required method -(void)clearListSelection.
  • I have an Objective-C class FooController with a public method matching that selector.
  • I have a Swift class BarController that inherits form FooController, and declares conformance to the Foo protocol.


Previously, this was all fine (as it would be if all parts were Objective-C). Now, the compiler "helpfully" renames the required method to clearSelection() in Swift. Thus:

  • BarController no longer conforms to Foo, because it doesn't implement the required method.
  • I can't add a method clearListSelection() to BarController, because the compiler says I need to override the inherited method.
  • Once I add that keyword, the compiler complains that the method has been renamed.
  • If I try to override clearSelection(), the compiler complains that there is no such method in the superclass.
  • And if I take off the override, it tells me the method has an Objective-C selector that conflicts with a method from its superclass.


So, the compiler seems to be smart enough to prevent me from taking a number of bad paths, but not smart enough to recognize the good path. It's hard for me to tell whether this is a bug, or something Swift 3 is deliberately making impossible. 😐


It does appear to be the case that I can add an NS_SWIFT_NAME attribute to the protocol declaration to get the compiler to stop "fixing" the name. But this still feels wrong to me.

Replies

Now, the compiler "helpfully" renames the required method to clearSelection() in Swift.

This is the bit that’s confusing me. I created a new project (Xcode 8.2) and added an Objective-C header that looks like this:

@protocol Foo <NSObject>

@required

- (void)clearListSection;

@end

I then implemented that in Swift like this:

class FooController : NSObject, Foo {
    func clearListSection() {
    }
}

There’s no renaming going on, and I’m not sure why there would be renaming going on in your project.

If you create a minimal test project as I’ve described above, do you still see the problem?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

There's a layer in our code that you've skipped in your example: the Swift class declares conformance, but inherits the method from an Objective-C superclass. But I have not yet tried to create a minimal test case, so there could be something else going on, too.