performSelector error with global function and AppDelegate class

703 views Asked by At

I'm following this apple document and I'm trying to translate some of its parts in Swift language. I have this global function, with performSelector:

func RunLoopSourceScheduleRoutine(info:UnsafeMutableRawPointer? ,rl:CFRunLoop? , mode:CFRunLoopMode?)  {

let obj :  RunLoopSource = Unmanaged<RunLoopSource>.fromOpaque(info!).takeUnretainedValue()
let del = UIApplication.shared
let theContext = RunLoopContext(withSource: obj, andLoop: rl!)

del.performSelector(onMainThread:#selector(AppDelegate.registerSource) , with: theContext, waitUntilDone: false)

}

And AppDelegate class, in this class there are: methods that automatically adds Xcode in the normal routine of project creation (didFinishLaunchingWithOptions, applicationWillResignActive, etc) I added the sourcesToPing parameter and the registerSource() method:

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?
    var sourcesToPing : [RunLoopContext] = Array()

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.

    return true
}

    func registerSource(sourceInfo:RunLoopContext)  {
    sourcesToPing.append(sourceInfo)
}

}

but the compiler get the following error , in RunLoopSourceScheduleRoutine() function:

argument '#selector' refers to instance method 'registerSources(source Info:)' that is not exposed to Objective-C

what is the problem ? and how does it solve?

1

There are 1 answers

5
Duncan C On BEST ANSWER

PerformSelector is an Objective-C method that predates GCD (Grand Central Dispatch). It should be possible to do it that way, but selectors are not type-safe and are awkward to use.

I'm not sure what's wrong with your current code. As Martin points out in his comment, the error you're reporting is complaining about a method called registerSources() but you show code for a method called registerSource() (with no final "e".) If you want to get that code working you need to get to the bottom of that discrepency.

Instead, why not use GCD code like this:

dispatchQueue.main.async() {
  registerSource(theContext)
}

That will accomplish the same goal but using the more modern GCD