Ios 如何为UIApplicationLegate实现协议方法?

Ios 如何为UIApplicationLegate实现协议方法?,ios,objective-c,Ios,Objective C,我在一个类中工作,称之为Module,我需要在AppDelegate中实现此方法: - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { ... } 我知道哪个类是AppDelegate(称之为App),但我

我在一个类中工作,称之为Module,我需要在AppDelegate中实现此方法:

- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication
         annotation:(id)annotation
{
   ...
}
我知道哪个类是AppDelegate(称之为App),但我无权编辑该类。如何从模块中实现委托方法

我曾考虑使用一个类别来扩展应用程序,但中的这一行令人担忧:

您需要在希望使用其他方法的任何源代码文件中导入类别头文件,否则会遇到编译器警告和错误


问题是,我如何在模块中实现协议方法,以便iOS知道在适当的时间调用我的协议方法?

好的,乔。。。如果要从另一个模块实现
应用程序:openURL:sourceApplication:annotation:
,可以在运行时完成

我们需要假设AppDelegate已经实现了这个方法

首先,您需要导入该类:

#import <objc/runtime.h>
if (!existMethod) {
        class_addMethod([[[UIApplication sharedApplication] delegate] class], openURLMethod->method_name, openURLMethod->method_imp, openURLMethod->method_types);
    }
最后,您可以通过以下方式更改实现:

//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;
    });
但是要小心。如果您查看我的代码,我将在我的实现中调用原始实现,因此如果我执行代码来更改多个实现,我的实现将是一个开始(就像电影一样,我的实现在我的实现中,在我的实现中,在我的实现中,在我的实现中等等)

编辑:

有一种方法可以将实现添加到类中:

如果
class\u getInstanceMethod
返回null,则可以为该方法分配内存,并在以后将其添加到类中:

//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;
    }
将方法添加到类中:

#import <objc/runtime.h>
if (!existMethod) {
        class_addMethod([[[UIApplication sharedApplication] delegate] class], openURLMethod->method_name, openURLMethod->method_imp, openURLMethod->method_types);
    }
但问题是,我想,当应用程序启动时,操作系统正在注册该方法,因此如果应用程序启动时该方法不存在,操作系统将永远不会调用您的方法


我将研究操作系统如何管理这些事件。使用
ApplicationIdentinterBackground
,如果您没有AppDelegate上的实现,并且您在运行时添加了它,那么操作系统永远不会调用您的实现。这就是为什么我假设在应用程序启动时操作系统正在注册事件。

这个问题是关于调用一个方法的,但我问的是如何实现UIApplicationLegate协议的一个方法。注意-我的第一条评论是对将其标记为可能重复并发表评论的人的回应,然后删除这些。是否要实现-(BOOL)应用程序。。。。来自另一个类?不必来自另一个类,但必须在我控制的代码中(我无法编辑应用程序)。我为App类编写了一个类别,但我认为没有调用protocol方法。它不会工作,因为需要在调用该方法的类中导入标题类别。您没有访问权限,因为它是一个系统类。有了我的答案,您可以在运行时更改应用程序委托的实现,我用协议ApplicationIdentinterBackground测试了这一点,它可以工作。我喜欢它!这是在事后实现协议方法的一种非常棘手的方法。但是,我恐怕不能假定该方法是在原始AppDelegate中实现的。我如何使用运行时实现一个原本不存在的方法?Joe,你可以看到我的编辑。。但问题是操作系统不调用该方法,我假设SO在应用程序启动时注册了该事件。让我来研究一下。@Bryan谢谢你提醒我方法swizzling-我记得很久以前读过它,但不记得它的名字。哇@BryanChen和Joe,我不知道swizzling方法。@Dcorbata您(更新)的技术声称能够向尚未实现该方法的类添加方法。JRSwizzle不会这样做:)