About performSelector return value
Asked Answered
C

3

5

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?

Cuprite answered 2/11, 2015 at 11:9 Comment(0)
C
8

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()
Couching answered 2/11, 2015 at 11:47 Comment(4)
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.Cuprite
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 SwiftCouching
@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.Achaea
In Swift 4 I get the error "Cannot invoke 'performSelector' with an argument list of type '(String)'"Tella
L
3

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
Loriloria answered 12/5, 2019 at 10:49 Comment(0)
O
0

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())
Overgrowth answered 27/11, 2017 at 23:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.