0

perform is NSObjectProtocol's function:

func perform(_ aSelector: Selector!) -> Unmanaged<AnyObject>!

func perform(_ aSelector: Selector!, with object: Any!) -> Unmanaged<AnyObject>!

func perform(_ aSelector: Selector!, with object1: Any!, with object2: Any!) -> Unmanaged<AnyObject>!

This is my code:

    func test() {
        let sel2 = #selector(newAction(pra:param:))
        perform(sel2, with: 2, with: "bbb")
    }
    
    @objc func newAction(pra: Int, param: String) {
        print("pra = \(pra), param = \(param)") // pra = -5251357295740329306, param = bbb
    }

The question Alternative to performSelector in Swift? answers the value type can't work by this way.But the String and Int are implement by struct, why can the String work by perform selector?

Albert
  • 3
  • 2
  • What is a guy named `perform()` supposed to do? – El Tomato Apr 22 '21 at 06:58
  • The `perform()` is system function. – Albert Apr 22 '21 at 07:13
  • 1
    I think it's to do with whether it is a "value type" in ObjC, not whether it is a value type in Swift. `Int` in Swift maps to `NSInteger` in ObjC (which is declared as `typedef long NSInteger`). OTOH, `String` in Swift maps to `NSString` in ObjC. – Sweeper Apr 22 '21 at 07:15
  • If you actually try to call `performSelector` in Objective-C, it doesn't even let you pass in integers as the arguments. Try `[someObject performSelector:@selector(someSelector:) withObject:1 withObject:2];`. – Sweeper Apr 22 '21 at 07:25
  • I try to invoke it in Objective-C, I agree with you.Thanks. – Albert Apr 22 '21 at 08:26

1 Answers1

1

Try:

func test() {
   let sel2 = #selector(newAction(pra:param:))
   perform(sel2, with: NSNumber(value: 2), with: "bbb")
}

@objc func newAction(pra: NSNumber, param: String) {
    print("pra = \(pra.intValue), param = \(param)")
    // or just
    print("pra = \(pra), param = \(param)")
}

Should also work:

func test() {
   let sel2 = #selector(newAction(pra:param:))
   perform(sel2, with: 2, with: "bbb")
}

@objc func newAction(pra: NSNumber, param: String) {
    print("pra = \(pra), param = \(param)")
}

The argument type needs to be a reference type. In Swift side, passing an Int to withObject: parameter makes that Int converted into NSNumber. But the Objective-C runtime does not automatically convert it back to Int. (Remember that Objective-C selectors do not have type information.)

Daniel Marx
  • 676
  • 5
  • 8