2013-11-21 3 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

Ok Joe ... Если вы хотите ОСУЩЕСТВИТЬ application:openURL:sourceApplication:annotation: из другого модуля, вы можете сделать это во время выполнения.

НУЖНО НЕСТИ ЧТО AppDelegate HAVE ТЕХ МЕТОД ВЫПОЛНЕНА

Сначала вам нужно импортировать класс:

#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; 
    }); 

НО БУДЬТЕ ОСТОРОЖНЫ. Если вы посмотрите в моем коде, я вызываю оригинальную реализацию внутри моей реализации, поэтому, если я выполню код, чтобы изменить реализацию более одного, моя реализация будет . Начало (Как и в фильме, моя реализация внутри моей реализации , внутри моей реализации, внутри моей реализации и т. д.).

EDIT:

Существует способ, чтобы добавить свою реализацию в класс:

Если class_getInstanceMethod возвращение нуля вы можете 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); 
    } 

Но проблема в том, что оперативная система регистрирует метод при запуске приложения, поэтому, если при запуске приложения метод не существует, ОС никогда не вызовет ваш метод.

Я буду исследовать, как ОС управляет событиями. С applicationDidEnterBackground, если у вас нет реализации в AppDelegate, и вы добавляете ее во время выполнения, OS никогда не вызывает вашу реализацию. Вот почему я предполагаю, что операционная система регистрирует события при запуске приложения.

+0

Мне это нравится! Это очень сложный способ реализовать метод протокола после факта. Но, боюсь, я не могу предположить, что метод был реализован в исходном AppDelegate. Как я могу использовать среду выполнения для реализации метода, который изначально не был там? –

+1

если вы хотите сделать метод swizzle, используйте https://github.com/rentzsch/jrswizzle –

+0

Joe, вы можете увидеть мое редактирование .. Но проблема в том, что ОС не вызывает метод, я предполагаю, что SO регистрируя событие, когда приложение запускается. Позвольте мне рассказать об этом. – dcorbatta

Смежные вопросы