1

I'm trying to create a protocol where one of the methods will return a dictionary of selector. But I'm running into an issue...

here is the protocol code:

@objc public protocol MazeProtocol: AnyObject {
    @objc static func configurations() -> [String:Selector]
}

and here is the compiler error I'm getting: MazeTableViewController.swift:12:24: Method cannot be marked @objc because its result type cannot be represented in Objective-C

If I remove the @objc in front of the method, I get a similar error.

Nilanshu Jaiswal
  • 1,583
  • 3
  • 23
  • 34
otusweb
  • 1,638
  • 1
  • 19
  • 30
  • 1
    Why did you add the @objc in the first place? Also, have you tried declaring your class like this: `public protocol MazeProtocol: class { ...` – Swifty Nov 23 '18 at 14:18

3 Answers3

3

Well [String: Selector] is Dictionary<String, Selector> which is a struct and structs cannot be represented in Objective-C, so you would need an NSDictionary

@objc public protocol MazeProtocol: AnyObject {
    @objc static func configurations() -> NSDictionary
}
olejnjak
  • 1,163
  • 1
  • 9
  • 23
0

As you can't use Selector in Objective C Dictionary directly, you can change your Swift dictionary's both key and value type to String as like below.

@objc public protocol MazeProtocol: AnyObject {
    @objc static func configurations() -> [String:String]
}

So when you want to get your Selector from configurations dictionary, get it as like below.

let selectorString = configurations()["KeyToSelector"]
let selector = NSSelectorFromString(selectorString)
Natarajan
  • 3,241
  • 3
  • 17
  • 34
0

As RX9 suggests, there's no reason (at least that you've explained) to mark this as @objc, at either the function or protocol level. The following is fine:

public protocol MazeProtocol: AnyObject {
    static func configurations() -> [String:Selector]
}

The point of @objc is to allow ObjC objects to interact with this protocol. If you have Objective-C that needs to interact with this protocol, I strongly suggest defining this protocol on the ObjC side rather than on the Swift side. (But if you have that case, leave a comment, and we can walk through how to get what you need; as olejnjak notes, you can't put Selector directly in a dictionary that ObjC understands.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • My goal is to have UIView and UIViewController adopt this protocol, so my understanding is that I need the @objc – otusweb Nov 26 '18 at 13:49
  • As long as the adoption is done in Swift, there's no need to mark this `@objc`. The implementation language of the superclass is not important. All that's important is the code that references the protocol and method. – Rob Napier Nov 26 '18 at 14:15
  • Actually I dove back in the code and I forgot that I use the objectiveC runtime to find which class adopt this protocol. hence the @objc. – otusweb Nov 26 '18 at 15:59
  • In that case, this method can't be marked `@objc` because `Selector` can't be the value of an `NSDictionary`. You'll need to rewrite it to use something other than `Selector` (generally you use `String` and use `NSStringFromSelector` and `NSSelectorFromString` to convert.) Note that this likely means that all implementing classes must also be `@objc`, so you probably mean `NSObject` rather than `AnyObject`. – Rob Napier Nov 26 '18 at 16:01
  • I was able to store the selector in the dictionary, but I'm getting compiler error further down. I created a new question with more background as technically this question was answered even though my overall problem is not fixed :-) I'd love for you to take a look: https://stackoverflow.com/questions/53502451/trying-to-call-selector-to-static-function-in-swift – otusweb Nov 27 '18 at 15:04