Can you swizzle application:didReceiveRemoteNotification:

旧城冷巷雨未停 提交于 2019-12-23 18:33:32

问题


I'm currently working on a product that needs to swizzle the AppDelegate's application:didReceiveRemoteNotification: (I don't want to call my new method in the appDelegate itself).

The thing is: the swizzling simply doesn't work. I've already swizzled methods several times before with success, and this time, the replacing implementation is simply not called. I was wondering if that was because of some specificity of the appDelegate's methods, since these are called by the system, and not the application.


回答1:


I am going to assume most of the things which are missing in your question, Its a great idea to always post the questions with code samples whenever possible.

  1. You need to make sure that you are swizzling your methods on the specific implementation of UIApplicationDelegate and NOT the UIApplicationDelegate itself. For Eg

    @interface AppDelegate : UIResponder <UIApplicationDelegate>
    @end
    

    In this case you need to swizzle the AppDelegate Class.

  2. Also, if you are trying to write a static library/framework you may not know the name of this class at all. In such cases simplest/safest way is to ask for App's AppDelegate name and use that to retrieve a specific class instance via NSClassFromString() or you can just brute force to find the class you need (because you usually have a Single AppDelegate class).

        unsigned int numberOfClasses = 0;
        Class *classes = objc_copyClassList(&numberOfClasses);
        Class appDelegateClass = nil;
        for (unsigned int i = 0; i < numberOfClasses; ++i) {
            if (class_conformsToProtocol(classes[i], @protocol(UIApplicationDelegate))) {
                appDelegateClass = classes[i];
            }
    }
    

EDIT

There are a few shortcomings of the above approach,

  1. It iterates over all the classes accessible by your application code, looping through all of these classes is not a performant solution.

  2. Many famous SDKs will swizzle or dynamically extend your AppDelegate, because a lot of interesting things can be intercepted at this single place. This also means that your application may have more than one implementation of UIApplicationDelegate protocol and the code above may just pick any implementation of it, causing some serious issues.

As, Chris suggested in comments below, its much safer and performant to just use [[UIApplication sharedApplication].delegate class]. which should give you the exact AppDelegate implementation known to iOS application at the moment of calling this line of code.



来源:https://stackoverflow.com/questions/20483159/can-you-swizzle-applicationdidreceiveremotenotification

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!