2013-11-21 108 views
0

我在一类的工作,把它叫做模块,我需要实现在AppDelegate中此方法:如何实现UIApplicationDelegate的协议方法?

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

我知道哪个类是AppDelegate中(称之为APP),但我没有访问编辑该类。我怎样才能从我的模块实现委托方法?

我想过使用一个类来扩展应用程序,但该线路category docs是一个问题:

“你需要导入的类头文件中的所有源代码文件,你要使用的额外的方法,否则你会遇到编译器警告和错误。“

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

+0

这个问题是关于调用一个方法,但我问的是实现UIApplicationDelegate协议的一个方法。 –

+0

请注意 - 我的第一条评论回应了某人将其标记为可能的重复并发表评论,然后将其删除。 –

+0

你是否想从另一个类实现 - (BOOL)应用程序.... – dcorbatta

回答

1

好的乔......如果你想从其他模块中实现application:openURL:sourceApplication:annotation:,你可以在运行时做到这一点。

我们需要假定的AppDelegate HAVE 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,你可以的Alloc该方法的内存并把它添加到类后:

//If the method dont exist. We need to create one. 
    if (!openURLMethod) { 
     existMethod = NO; 
     openURLMethod = malloc(sizeof(struct objc_method)); 
     openURLMethod->method_types = "[email protected]:[email protected]@[email protected]@20"; 
     openURLMethod->method_name = selectorOpenURL; 
    } 

添加方法的类:

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

但是问题是,我想操作系统是在应用程序启动时注册方法的,所以如果应用程序启动的方法不存在,OS永远不会调用您的方法。

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

+0

我喜欢它!事实之后,这是一种非常棘手的方式来实现协议方法。但是,我担心我不能假定该方法是在原始AppDelegate中实现的。我如何使用运行时来实现原本不存在的方法? –

+1

如果你想做方法swizzle,使用https://github.com/rentzsch/jrswizzle –

+0

乔,你可以看到我的编辑..但问题是,操作系统不调用的方法,我假设SO是在应用程序启动时注册事件。让我研究一下。 – dcorbatta