如何实现UIApplicationDelegate的协议方法?

时间:2013-11-21 01:42:26

标签: ios objective-c

我在一个班级工作,称之为模块,我需要在AppDelegate中实现这个方法:

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

我知道哪个类是AppDelegate(称之为App),但我无权编辑该类。如何从我的模块中实现委托方法?

我考虑使用类别来扩展App,但category docs中的这一行是一个问题:

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

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

1 个答案:

答案 0 :(得分:1)

Ok Joe ...如果你想从另一个模块中实现application:openURL:sourceApplication:annotation:,你可以在运行时完成它。

我们需要确定AppDelegate是否实施了TEH方法

首先,您需要导入该类:

#import <objc/runtime.h>

然后你需要声明一个对象方法的结构:

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

最后你可以改变这个实现:

//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_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;
    }

将方法添加到课程中:

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

但问题是,我认为操作系统在应用程序启动时正在注册该方法,因此如果应用程序启动时该方法不存在,操作系统将永远不会调用您的方法。

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