简体   繁体   English

如何实现UIApplicationDelegate的协议方法?

[英]How to implement protocol method for the UIApplicationDelegate?

I'm working in a class, call it Module, and I need to implement this method in the AppDelegate: 我正在一个类中工作,将其称为模块,并且需要在AppDelegate中实现此方法:

- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication
         annotation:(id)annotation
{
   ...
}

I know which class is the AppDelegate (call it App), but I do not have access to edit that class. 我知道哪个类是AppDelegate(称为App),但是我无权编辑该类。 How can I implement the delegate method from my Module? 如何从我的模块中实现委托方法?

I thought about using a category to extend App but this line in the category docs is a concern: 我考虑过使用类别来扩展App,但是类别文档中的这一行值得关注:

"you'll need to import the category header file in any source code file where you wish to use the additional methods, otherwise you'll run into compiler warnings and errors." “您将需要在要使用其他方法的任何源代码文件中导入类别头文件,否则会遇到编译器警告和错误。”

The question is, how can I implement the protocol method in my module in a way so that iOS knows to call my protocol method at the appropriate time? 问题是,如何以某种方式在模块中实现协议方法,以便iOS知道在适当的时间调用我的协议方法?

Ok Joe... If you want to IMPLEMENT the application:openURL:sourceApplication:annotation: from another module, you can do it in runtime. 好的,乔...如果您想在另一个模块中实现application:openURL:sourceApplication:annotation: ,则可以在运行时执行。

WE NEED TO ASSUME THAT THE AppDelegate HAVE TEH METHOD IMPLEMENTED 我们需要确保AppDelegate实施了以下方法

First you need to import the class: 首先,您需要导入该类:

#import <objc/runtime.h>

Then the you need to declare the struct of an object method: 然后,您需要声明一个对象方法的结构:

struct objc_method {
    SEL method_name;
    char *method_types;
    IMP method_imp;
};

And finally you can change the implementation whit this: 最后,您可以更改实现:

//Create the selector of the method.
    NSString * openURL = @"application:openURL:sourceApplication:annotation:";
    SEL selectorOpenURL = NSSelectorFromString(openURL);

    //Get the method of the intance.
    Method openURLMethod = class_getInstanceMethod([[[UIApplication sharedApplication] delegate] class], selectorOpenURL);

    //Get the current implementation.
    IMP openURLIMP = openURLMethod->method_imp;

    //Create your own implementation.
    IMP myOpenURLIMP = imp_implementationWithBlock(^BOOL(id _s, UIApplication * app,NSURL *url,NSString *sourceApplication,id annotation) {

        //Call the original implementation.
        openURLIMP(_s,selectorOpenURL,app,url,sourceApplication,annotation);

        //Here your implementation code.
        NSLog(@"Handling the URL");

        return YES;
    });

BUT BE CAREFUL. 不过要小心。 If you look in my code, I'm calling the original implementation inside my implementation, so if I execute the code to change the implementation more than one, my implementation will be an inception (Like the film, my implementation inside my implementation, inside my implementation, inside my implementation and so on). 如果您查看我的代码,我将在实现内部调用原始实现,因此,如果我执行该代码以更改一个以上的实现,那么我的实现将是一个开始 (就像电影一样,我的实现位于内部,内部我的实施,在我的实施之内等等)。

EDIT: 编辑:

There is way to add your implementation to the class: 有一种方法可以将实现添加到类中:

If class_getInstanceMethod return null you can alloc the memory for the method and add it to the class later: 如果class_getInstanceMethod返回null,则可以为该方法class_getInstanceMethod内存,并在以后将其添加到类中:

//If the method dont exist. We need to create one.
    if (!openURLMethod) {
        existMethod = NO;
        openURLMethod = malloc(sizeof(struct objc_method));
        openURLMethod->method_types = "c24@0:4@8@12@16@20";
        openURLMethod->method_name = selectorOpenURL;
    }

Adding the method to the class: 将方法添加到类中:

if (!existMethod) {
        class_addMethod([[[UIApplication sharedApplication] delegate] class], openURLMethod->method_name, openURLMethod->method_imp, openURLMethod->method_types);
    }

But the problem is, I suppose, that the Operative System are registering the method when the app start, so if when the app start the method don't exist the OS never will call your method. 但是,我想问题是,当应用程序启动时,操作系统正在注册该方法,因此,如果在应用程序启动时该方法不存在,则OS永远不会调用您的方法。

I will research about how the OS are management that events. 我将研究操作系统如何管理事件。 With the applicationDidEnterBackground , if you don't have the implementation on the AppDelegate and you add it in runtime, the OS never call your implementation. 使用applicationDidEnterBackground ,如果您在AppDelegate上没有实现,而是在运行时添加它,则OS永远不会调用您的实现。 This is why I assume that the operating system is registering the events when the application starts. 这就是为什么我假设操作系统在应用程序启动时正在注册事件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM