"No visible interface" error on category after swift Swift 4 migration

Viewed 2573

I started the migration of a project with the recommended wizard on Xcode 9 over a project that has both Objc and Swift working together.

The problem occurs when having the following UIColor extension:

extension UIColor {
    func doSomething(withAnotherColor color: UIColor) -> Bool {
        return true
    }
}

then on some Objc class:

@implementation MyView

    - (void)styleView {
        //... some code
        if ([someColor doSomethingWithAnotherColor:anotherColor]) {
            ... 
        }
    }
@end

The if statement is throwing the following error: ../MyView.m: No visible @interface for 'UIColor' declares the selector 'doSomethingWithAnotherColor:'

I tried using @objc directive both on the extension and method without luck.

Note this is a compilation error, not a warning like mentioned on other questions, like this one: How can I deal with @objc inference deprecation with #selector() in Swift 4?

Any ideas?

2 Answers

I fixed the problem by explicitly specifying the method signature in swift function's @objc annotation

// Swift codes

@objc(myNoArgFunc) // need to specify even if the obj-c method name is the same as the swift name
func myNoArgFunc() {
}

@objc(myFuncWithArg1:arg2:arg3:) // note the last :
func myFunc(_ arg1: String, arg2: String, arg3: int) {
}

In essence, @matt's solution is the right approach. On my specific case another things were happening

Here some comments:

  • There is no need to prefix the entire extension with @objc, adding the prefix to the function only did the trick.
  • As a mentioned on another comment, I tried this before posting but was not working, but since @matt suggested it I decided to delete all drived data, reopen the project and tried this again, now the problem was another thing (next point)
  • Apparently the way functions were translated from Swift to Objc has changed, I used to have:

Swift (UIColor category):

func doSomething(anotherColor: UIColor) -> Bool

In objc before the update, I was able to:

[aColor doSomething:anotherColor];

But after the update I needed to change it to:

[aColor doSomethingAnotherColor:anotherColor];

In order to keep using the function the same way in Objc, you can change the Swift function to:

func doSomething(_ anotherColor: UIColor) -> Bool

And that was whole the problem on my end. Hope this helps someone.

Related