1

I have a function declared like this:

func rspGetCategories(_ response: (Int, [String:Any])) {

I try to call it like this:

self.perform(act, with: (tag, outjson))

Where:

act = Selector(("rspGetCategories:"))
tag = 1
outjson = ["status":"ServerError"]

I just get an "unrecognized selector sent...". What am I missing here?

Full error message:

    2018-07-18 11:20:15.852755+0200 Appname[8071:4529543] -[Appname.ViewController rspGetCategories:]: unrecognized selector sent to instance 0x10380be00
2018-07-18 11:20:15.853361+0200 Appname[8071:4529543] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Appname.ViewController rspGetCategories:]: unrecognized selector sent to instance 0x10380be00'
*** First throw call stack:
(0x18418ed8c 0x1833485ec 0x18419c098 0x18e27edb0 0x1841945c8 0x18407a41c 0x1020f5dfc 0x1020ebc3c 0x102f811dc 0x102f8119c 0x102f85d2c 0x184137070 0x184134bc8 0x184054da8 0x186039020 0x18e071758 0x1020fec34 0x183ae5fc0)
libc++abi.dylib: terminating with uncaught exception of type NSException
Richard G. Nielsen
  • 1,221
  • 10
  • 13

2 Answers2

1

Split your tuple into two parameters like

@objc func rspGetCategories(_ response: Int, dict: [String: Any]) {

and change the selector

let act = #selector(Test.rspGetCategories(_:dict:))

Test is the name of my class, replace it with your class name

Joakim Danielson
  • 43,251
  • 5
  • 22
  • 52
1

As the selector method should be representable by Objective-C so with @objc, we can not pass tuple as parameter for a method otherwise compiler will throw this error,

Method cannot be marked @objc because the type of the parameter cannot be represented in Objective-C

One possible solution is as below,

@objc func rspGetCategories(_ response: [String: Any]) {
    print("Tag: \(response["tag"] as! Int) Status:\(response["status"] as! String)")
}

And construct the response as below,

let selector = #selector(rspGetCategories(_:))
let tag = 1
let response: [String: Any] = ["tag": tag,
                               "status": "ServerError"]
self.perform(selector, with: response)

Another solution is to pass two parameters instead of tuple. As below,

@objc func rspGetCategories(_ tag: NSNumber, response: [String: Any]) {
    print("\(tag.intValue) \(response)")
}

let selector = #selector(rspGetCategories(_:response:))
let tag = 1
let response = ["status": "ServerError"]
self.perform(selector, with: tag, with: response)

Remember that selector method argument type needs to be a reference type.

Kamran
  • 14,987
  • 4
  • 33
  • 51
  • Something strange is happening, though... I went for the second approach, and it seems the value of tag gets corrupted. When I pass 0 in tag, it is received in rspGetCategories as -5764607523034234877 – Richard G. Nielsen Jul 18 '18 at 14:18
  • @RichardG.Nielsen Yes, just checked that code. Actually method to be called from perform should have reference type parameters to work consistently. – Kamran Jul 18 '18 at 15:59
  • You will need a little update in method signature as `rspGetCategories(_ tag: NSNumber, response: [String: Any])` and then you can use the `tag.intValue` to get the integer value. I hope this will fix the issue. – Kamran Jul 18 '18 at 16:00
  • I found the exact same solution, and came here to tell about it, but you beat me to it. :) – Richard G. Nielsen Jul 18 '18 at 17:28