Есть ли способ в obj-c подключиться к методам делегата приложения
Проблема в том, что:
Я использую Marmalade SDK ( https://www.madewithmarmalade.com/).
Marmalade SDK предлагает возможность написания специфичных для платформы плагинов (расширение в их терминологии).
Каждое расширение скомпилировано как статическая библиотека и связано с основным приложением (Loader в их терминологии) с помощью специального инструмента развертывания.
Источники основного приложения не открываются, поэтому у нас нет возможности реализовать / переопределить методы делегата приложения.
Мне нужно расширение для управления удаленными push-уведомлениями через Upsight SDK (ранее PLayhaven).
ios 8 пришел и требует дополнительных усилий для регистрации удаленных push-уведомлений. В частности, должны быть реализованы didRegisterForRemoteNotificationsWithDeviceToken и didRegisterUserNotificationSettings.
Вопросы:
Как я могу внедрить в методы делегата приложения из статической библиотеки (не имея доступа к источникам основного приложения)?
Мысли были:
1) Использование категорий. Я попытался добавить новые методы в класс UIApplication, а затем обменял их на оригинальные. Мои новые методы сделали свое дело, а затем вызвали оригинальные методы. Но, похоже, не работает. Мой опыт работы с объектами довольно плохой. Либо мое расширение класса было неправильно реализовано, либо исходная идея была неправильной:
@interface UIApplication(MyDelegate)
- (void)application:(UIApplication *)application newDidRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings;
@end
@implementation UIApplication(MyDelegate)
- (void)application:(UIApplication *)application newDidRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
NSLog(@"PLAYHAVEN: didRegisterUserNotificationSettings:%@", notificationSettings);
[[PHPushProvider sharedInstance] registerUserNotificationSettings:notificationSettings];
}
@end
s3eResult s3ePlayhavenInit_platform()
{
// Add any platform-specific initialisation code here
myDelegate = [[MyDeleagte alloc] init];
oldHandler1 = class_getInstanceMethod([UIApplication class], @selector(application:didRegisterUserNotificationSettings:));
newHandler1 = class_getInstanceMethod([UIApplication class], @selector(application:newDidRegisterUserNotificationSettings:));
method_exchangeImplementations(oldHandler1, newHandler1);
...
return S3E_RESULT_SUCCESS;
}
2) С помощью NSNotificationCenter прослушайте соответствующие уведомления:
[[NSNotificationCenter defaultCenter] addObserver:myDelegate selector:@selector(didRegisterUserNotificationSettings:) name:@"UIApplicationDidRegisterUserNotificationSettings" object:nil];
Но я не уверен, что уведомление с таким именем будет вообще размещено. Мне не удалось найти какие-либо соответствующие константы в классе UIApplication. В результате это также не работает.
Последний вопрос:
Это вообще возможно? Есть идеи?
Спасибо всем.
1 ответ
Этот метод (1) будет работать отдельно от функции didRegisterUserNotificationSettings, являющейся частью UIApplicationDelegate. Хитрость для получения правильного делегата состоит в том, чтобы перехватить функцию setDelegate UIApplication, а затем выполнить метод, перебивающий класс делегата.