Swift protocol as an init parameter called from Objective C class

986 Views Asked by At

I have a swift protocol which i have defined for testing openUrl functionality in iOS. It looks something like this:

protocol URLOpener {

    func open(_ url: URL, options: [String : Any], completionHandler completion: ((Bool) -> Void)?)
    func canOpenURL(_ url: URL) -> Bool

}

extension UIApplication: URLOpener {}

Note that UIApplication is class is conformed to this protocol.

Now i have a class which takes an object URLOpener type to initilize that class

import Foundation
class GenericHandler : NSObject {

    required init(urlOpener: URLOpener) {
        super.init()
    }

    func aaa() {
        NBLog("aaaaa")
    }
}

I want to use this GenericHandler class from Objective C but i gives me an error that it could not find the initilizer.

  GenericHandler *handler = [[GenericHandler alloc] initWithUrlOpener:[UIApplication sharedApplication]];
        [handler aaa];

 No visible @interface for 'GenericHandler' declares the selector 'initWithUrlOpener:'

However if i change the initizer so that it accepts String parameter then it starts to work fine.

import Foundation
class GenericHandler : NSObject {

    required init(urlOpener: String) {
        super.init()
    }

    func aaa() {
        NBLog("aaaaa")
    }

}



GenericHandler *handler = [[GenericHandler alloc] initWithUrlOpener:@"test"];
        [handler aaa];

This just works fine. Can anyone guide me whats the issue withURLOpener protocol or how i can make it working with URLOpener parameter.

1

There are 1 best solutions below

0
On

A bit late, but I just struggled with the same question.

You have to expose both the protocol and the init to Objective-C.

@objc protocol URLOpener {
    func open(_ url: URL, options: [String : Any], completionHandler completion: ((Bool) -> Void)?)
    func canOpenURL(_ url: URL) -> Bool
}

extension UIApplication: URLOpener {}

-

import Foundation

class GenericHandler : NSObject {

    @objc required init(urlOpener: URLOpener) {
        super.init()
    }

    func aaa() {
        NBLog("aaaaa")
    }
}

You can always check your generated header file to see if your Swift code is available in Objective-C. See the paragraph "Importing Swift into Objective-C" from the Apple docs.