如何覆盖包含块的objC中的方法?
How to override a method in objC which includes a block?
我知道如何覆盖 Objective-C 中的方法。我按照以下步骤操作,一切正常。问题是当原始方法包含一个块时,我不知道该怎么做。如果您能 fix/add 到我下面的代码,我将不胜感激。
在下面的代码中,我用我不知道如何覆盖的块注释掉了方法。仅供参考:我正在覆盖与推送通知服务相关的代码。
id delegate = [[UIApplication sharedApplication] delegate];
Class objectClass = object_getClass(delegate);
NSString *newClassName = [NSString stringWithFormat:@"Custom_%@", NSStringFromClass(objectClass)];
Class modDelegate = NSClassFromString(newClassName);
if (modDelegate == nil)
{
modDelegate = objc_allocateClassPair(objectClass, [newClassName UTF8String], 0);
SEL selectorToOverride4 = @selector(application:didRegisterForRemoteNotificationsWithDeviceToken:);
SEL selectorToOverride5 = @selector(application:didFailToRegisterForRemoteNotificationsWithError:);
SEL selectorToOverride6 = @selector(application:didReceiveRemoteNotification:);
//SEL selectorToOverride7 = @selector(application:didReceiveRemoteNotification:fetchCompletionHandler:);
// get the info on the method we're going to override
Method m4 = class_getInstanceMethod(objectClass, selectorToOverride4);
Method m5 = class_getInstanceMethod(objectClass, selectorToOverride5);
Method m6 = class_getInstanceMethod(objectClass, selectorToOverride6);
//Method m7 = class_getInstanceMethod(objectClass, selectorToOverride7);
// add the method to the new class
class_addMethod(modDelegate, selectorToOverride4, (IMP)didRegisterSuccess, method_getTypeEncoding(m4));
class_addMethod(modDelegate, selectorToOverride5, (IMP)didRegisterFailure, method_getTypeEncoding(m5));
class_addMethod(modDelegate, selectorToOverride6, (IMP)didReceiveRemoteNotification, method_getTypeEncoding(m6));
//class_addMethod(modDelegate, selectorToOverride7, (IMP)didReceiveRemoteNotificationFetchCompletionHandler, method_getTypeEncoding(m7));
// register the new class with the runtime
objc_registerClassPair(modDelegate);
}
// change the class of the object
object_setClass(delegate, modDelegate);
void didRegisterSuccess(id self, SEL _cmd, UIApplication *application, NSData *deviceToken)
{
[base didRegisterSuccess:application deviceToken:deviceToken];
}
void didRegisterFailure(id self, SEL _cmd, UIApplication *application, NSError *error)
{
[base didRegisterFailure:application error:error];
}
void didReceiveRemoteNotification(id self, SEL _cmd, UIApplication *application, NSDictionary *userInfo)
{
[base didReceiveRemoteNotification:application userInfo:userInfo];
}
/*
void didReceiveRemoteNotificationFetchCompletionHandler(id self, SEL _cmd, UIApplication *application, NSDictionary *userInfo, void(^)(UIBackgroundFetchResult)handler)
{
}
*/
块只是 Objective-C 个对象,因此您可以简单地使用 id
作为块的类型:
void didReceiveRemoteNotificationFetchCompletionHandler(id self, SEL _cmd, UIApplication *application, NSDictionary *userInfo, id handler)
{
}
或者您可以为您的块定义自己的类型,并使用它:
typedef void (^YourBlockType)(UIBackgroundFetchResult);
void didReceiveRemoteNotificationFetchCompletionHandler(id self, SEL _cmd, UIApplication *application, NSDictionary *userInfo, YourBlockType handler)
{
}
我知道如何覆盖 Objective-C 中的方法。我按照以下步骤操作,一切正常。问题是当原始方法包含一个块时,我不知道该怎么做。如果您能 fix/add 到我下面的代码,我将不胜感激。
在下面的代码中,我用我不知道如何覆盖的块注释掉了方法。仅供参考:我正在覆盖与推送通知服务相关的代码。
id delegate = [[UIApplication sharedApplication] delegate];
Class objectClass = object_getClass(delegate);
NSString *newClassName = [NSString stringWithFormat:@"Custom_%@", NSStringFromClass(objectClass)];
Class modDelegate = NSClassFromString(newClassName);
if (modDelegate == nil)
{
modDelegate = objc_allocateClassPair(objectClass, [newClassName UTF8String], 0);
SEL selectorToOverride4 = @selector(application:didRegisterForRemoteNotificationsWithDeviceToken:);
SEL selectorToOverride5 = @selector(application:didFailToRegisterForRemoteNotificationsWithError:);
SEL selectorToOverride6 = @selector(application:didReceiveRemoteNotification:);
//SEL selectorToOverride7 = @selector(application:didReceiveRemoteNotification:fetchCompletionHandler:);
// get the info on the method we're going to override
Method m4 = class_getInstanceMethod(objectClass, selectorToOverride4);
Method m5 = class_getInstanceMethod(objectClass, selectorToOverride5);
Method m6 = class_getInstanceMethod(objectClass, selectorToOverride6);
//Method m7 = class_getInstanceMethod(objectClass, selectorToOverride7);
// add the method to the new class
class_addMethod(modDelegate, selectorToOverride4, (IMP)didRegisterSuccess, method_getTypeEncoding(m4));
class_addMethod(modDelegate, selectorToOverride5, (IMP)didRegisterFailure, method_getTypeEncoding(m5));
class_addMethod(modDelegate, selectorToOverride6, (IMP)didReceiveRemoteNotification, method_getTypeEncoding(m6));
//class_addMethod(modDelegate, selectorToOverride7, (IMP)didReceiveRemoteNotificationFetchCompletionHandler, method_getTypeEncoding(m7));
// register the new class with the runtime
objc_registerClassPair(modDelegate);
}
// change the class of the object
object_setClass(delegate, modDelegate);
void didRegisterSuccess(id self, SEL _cmd, UIApplication *application, NSData *deviceToken)
{
[base didRegisterSuccess:application deviceToken:deviceToken];
}
void didRegisterFailure(id self, SEL _cmd, UIApplication *application, NSError *error)
{
[base didRegisterFailure:application error:error];
}
void didReceiveRemoteNotification(id self, SEL _cmd, UIApplication *application, NSDictionary *userInfo)
{
[base didReceiveRemoteNotification:application userInfo:userInfo];
}
/*
void didReceiveRemoteNotificationFetchCompletionHandler(id self, SEL _cmd, UIApplication *application, NSDictionary *userInfo, void(^)(UIBackgroundFetchResult)handler)
{
}
*/
块只是 Objective-C 个对象,因此您可以简单地使用 id
作为块的类型:
void didReceiveRemoteNotificationFetchCompletionHandler(id self, SEL _cmd, UIApplication *application, NSDictionary *userInfo, id handler)
{
}
或者您可以为您的块定义自己的类型,并使用它:
typedef void (^YourBlockType)(UIBackgroundFetchResult);
void didReceiveRemoteNotificationFetchCompletionHandler(id self, SEL _cmd, UIApplication *application, NSDictionary *userInfo, YourBlockType handler)
{
}