About performSelector return value

Related searches

Everyone knows that ios making support for "performSelector" in swift2.0 I want to know how can get the performSelector return value?

let returnValue:Unmanaged<AnyObject> = (self.dataSource?.performSelector("myselector:", withObject: self))!
let value : Int? = returnValue.takeRetainedValue() as? Int

There is a crash at the last line, How can I get the value from "performSelector" in swift2.0?

I think currently the performSelector in Swift only supports return value conforming to AnyObject, in your case you have Int which does not. In this case, performSelector will return nil, and your code is explicitly unwrapping the Optional making the program crash.

So one way to work around this is to make a method that returns NSNumber.

You can try this code in playground:

@objc class B: NSObject {
  func myselector(arg: A) -> NSNumber {
    return 0
  }
}

@objc class A: NSObject {
  var dataSource: B? = B()
  func a() -> Int {
    let returnValue = self.dataSource?.performSelector("myselector:", withObject: self)
    let value = returnValue?.takeRetainedValue() as! NSNumber
    return value.integerValue
  }
}

A().a()

About performSelector return value, 3 Answers. I think currently the performSelector in Swift only supports return value conforming to AnyObject , in your case you have Int which does not. In this case, performSelector will return nil, and your code is explicitly unwrapping the Optional making the program crash. What will the return value for performSelector: if I pass a selector that returns a primitive type (on object), such as 'week' on NSDateComponents (which will return an int)?

Use takeUnretainedValue:

let foo = Foo()
let value = foo.performSelector(Selector("bar")) //type of value is Unmanaged<AnyObject?>
let uvalue = value.takeUnretainedValue() //type of uvalue is now AnyObject?
let result = value as? String //type of result is now String

Updated for Swift 5:

also works with NSSelectorFromString: say you have a UIViewController called aViewController.

let value = aViewController.perform(NSSelectorFromString("view")) //type of value is Unmanaged<AnyObject?>
let uvalue = value.takeUnretainedValue() //type of uvalue is now AnyObject?
let myView = value as? UIView //type of result is now UIView

performSelector:, If aSelector is NULL , an NSInvalidArgumentException is raised. Return Value. An object that is the result of the message. Discussion. The performSelector:� This method is the same as perform Selector: except that you can supply an argument for a Selector. a Selector should identify a method that takes a single argument of type id.

You can get NSInteger result of performSelector by the following way

let returnValue = dataSource?.perform(#selector(myselector:), withObject: self)!
let value = Int(bitPattern: returnValue.toOpaque())

performSelector:withObject:, aSelector should identify a method that takes a single argument of type id. For methods with other argument types and return values, use NSInvocation . To add the return type you need to add arrow ( ->) and the return type. func funcname -> ReturnType { //statements return value } performSelector:, If aSelector is NULL , an NSInvalidArgumentException is raised. Return Value. An object that is the result of the message. Discussion. The performSelector: Return Value. An object that is the result

To receive the latest developer news, visit and subscribe to our News and Updates.

A Selector that identifies the method to invoke. The method should not have a significant return value and should take a single argument of type id, or no arguments.

The method should not have a significant return value and should take a single argument of type id, or no arguments. arg The argument to pass to the method when it is invoked.

Comments
  • You are right,but in my case the selector is not designed by myself, it is the system API witch return Int. I should make others try,thank you all the same.
  • So the api you are using is a private api that it is not included in the header right? One work around shall be wrapping the api into NSNumber by Objective-C then use that wrapped one in Swift
  • @Eric: You can just declare the undeclared method you want to use in a dummy category. You don't need to implement the category -- just declare it so that the compiler knows its signature. Put the declaration in your bridging header. Then Swift can use it directly.
  • In Swift 4 I get the error "Cannot invoke 'performSelector' with an argument list of type '(String)'"