Search code examples
swiftselector

Run method on class knowing only its name


how can I launch method knowing its name (as String)

// key.rawValue.firstUppercased is `ApiAddress`
let result = preferencesRepository.perform(Selector("get\(key.rawValue.firstUppercased)"))

where preferencesRepository has method getApiAddress() and conforms to NSObject

public class RealPreferencesRepository: NSObject {
    func getApiAddress() -> String
// ...

I have fatal error:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: '-[PreferencesModule.RealPreferencesRepository getApiAddress]:
unrecognized selector sent to instance 0x600000090a70'

thanks for help in advance


Solution

  • You need to prefix the getApiAddress() method with @objc attribute.

    Also, since the return value of the perform method is Unmanaged, you need to use takeRetainedValue() to convert the return value.

    public class RealPreferencesRepository: NSObject {
        @objc func getApiAddress() -> String {
            return "success"
        }
    }
    
    let preferencesRepository = RealPreferencesRepository()
    
    let result = preferencesRepository.perform(Selector("getApiAddress"))
    let value = result?.takeRetainedValue() as! String
    print(value)
    // => success