Ios 关于方法\u ExchangeImplements不同类中的交换方法
在AppDelegate.h文件中: @实现AppDelegateIos 关于方法\u ExchangeImplements不同类中的交换方法,ios,objective-c,runtime,Ios,Objective C,Runtime,在AppDelegate.h文件中: @实现AppDelegate @implementation zzFlowMonitor ...... void applicationFlowMonitor_original(id selfApp, SEL selector,UIApplication *app, CH_T completionHandler) { NSLog(@"applicationFlowMonitor_original to do something...");
@implementation zzFlowMonitor
......
void applicationFlowMonitor_original(id selfApp, SEL selector,UIApplication *app, CH_T completionHandler)
{
NSLog(@"applicationFlowMonitor_original to do something...");
completionHandler(UIBackgroundFetchResultNewData);
}
-(void) applicationFlowMonitor_swizzling:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
[[zzFlowMonitor shareInstance] refreshBackFetchHandle];
NSLog(@"applicationFlowMonitor_swizzling to do something...");
//call performFetchWithCompletionHandler delegate in appDelegate.
//an error occurred.*********************************************
[self applicationFlowMonitor_swizzling:application performFetchWithCompletionHandler:completionHandler];
}
-(void)startFlowMonitor:(Class)cla NS_AVAILABLE_IOS(7_0)
{
static dispatch_once_t oncetoken;
dispatch_once(&oncetoken, ^{
[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];
Method performFetchWCH = class_getInstanceMethod(cla, @selector(application:performFetchWithCompletionHandler:));
BOOL didAddMethod = class_addMethod(cla, @selector(application:performFetchWithCompletionHandler:), (IMP)applicationFlowMonitor_original, method_getTypeEncoding(performFetchWCH));
if(!didAddMethod){
SEL swizzledSelector = @selector(applicationFlowMonitor_swizzling:performFetchWithCompletionHandler:);
Method swizzledMethod = class_getInstanceMethod([zzFlowMonitor class], swizzledSelector);
method_exchangeImplementations(performFetchWCH, swizzledMethod);
}
});
}
@end
错误消息:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[[zzFlowMonitor shareInstance] startFlowMonitor:[AppDelegate class]];
return YES;
}
- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^) (UIBackgroundFetchResult))completionHandler {
NSLog(@"application to do something...");
completionHandler(UIBackgroundFetchResultNewData);
}
@end
我知道AppDelegate.m中没有applicationFlowMonitor\u swizzling方法,但我不知道如何修复它,我需要在不同的接口中替换方法。zzFlowMonitor是一个库,我想在我的库中钩住后台获取事件。非常感谢。简而言之,如果您不想以这种方式工作,您需要改为:
2015-08-10 14:26:44.256 FlowHome[18120:3350484] -[AppDelegate applicationFlowMonitor_swizzling:performFetchWithCompletionHandler:]: unrecognized selector sent to instance 0x7fc8386077f0
2015-08-10 14:26:44.259 FlowHome[18120:3350484] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[AppDelegate applicationFlowMonitor_swizzling:performFetchWithCompletionHandler:]: unrecognized selector sent to instance 0x7fc8386077f0'
*** First throw call stack:
(
0 CoreFoundation 0x0000000105da0c65 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x0000000105a39bb7 objc_exception_throw + 45
2 CoreFoundation 0x0000000105da80ad -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
3 CoreFoundation 0x0000000105cfe13c ___forwarding___ + 988
4 CoreFoundation 0x0000000105cfdcd8 _CF_forwarding_prep_0 + 120
5 FlowHome 0x00000001053dbfd5 -[zzFlowMonitor applicationFlowMonitor_swizzling:performFetchWithCompletionHandler:] + 197
6 UIKit 0x00000001061a8c59 -[UIApplication _handleNonLaunchSpecificActions:forScene:withTransitionContext:] + 671
7 UIKit 0x00000001061ace31 __88-[UIApplication _handleApplicationLifecycleEventWithScene:transitionContext:completion:]_block_invoke + 196
8 UIKit 0x00000001061acd5e -[UIApplication _handleApplicationLifecycleEventWithScene:transitionContext:completion:] + 349
9 UIKit 0x00000001061977ba -[UIApplication scene:didUpdateWithDiff:transitionContext:completion:] + 486
10 FrontBoardServices 0x00000001088485e5 __31-[FBSSerialQueue performAsync:]_block_invoke_2 + 21
11 CoreFoundation 0x0000000105cd441c __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
12 CoreFoundation 0x0000000105cca165 __CFRunLoopDoBlocks + 341
13 CoreFoundation 0x0000000105cc9f25 __CFRunLoopRun + 2389
14 CoreFoundation 0x0000000105cc9366 CFRunLoopRunSpecific + 470
15 GraphicsServices 0x00000001091b4a3e GSEventRunModal + 161
16 UIKit 0x00000001061998c0 UIApplicationMain + 1282
17 FlowHome 0x00000001053dc22f main + 111
18 libdyld.dylib 0x0000000107593145 start + 1
19 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
您正在交换这两个方法的实现,因此
self
将是您的应用程序代理,但不会有签名为-(void)applicationFlowMonitor\u swizzling:(UIApplication*)application performFetchWithCompletionHandler:(void(^)(UIBackgroundFetchResult))的方法completionHandler
,因为您从未添加该方法。该方法在zzFlowMonitor
中辞职,但其实现将是应用程序委托中定义的-(void)application:(UIApplication*)application performFetchWithCompletionHandler:(void(^)(UIBackgroundFetchResult))completionHandler
中的一个,如果您不想以这种方式工作,您需要改为:
2015-08-10 14:26:44.256 FlowHome[18120:3350484] -[AppDelegate applicationFlowMonitor_swizzling:performFetchWithCompletionHandler:]: unrecognized selector sent to instance 0x7fc8386077f0
2015-08-10 14:26:44.259 FlowHome[18120:3350484] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[AppDelegate applicationFlowMonitor_swizzling:performFetchWithCompletionHandler:]: unrecognized selector sent to instance 0x7fc8386077f0'
*** First throw call stack:
(
0 CoreFoundation 0x0000000105da0c65 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x0000000105a39bb7 objc_exception_throw + 45
2 CoreFoundation 0x0000000105da80ad -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
3 CoreFoundation 0x0000000105cfe13c ___forwarding___ + 988
4 CoreFoundation 0x0000000105cfdcd8 _CF_forwarding_prep_0 + 120
5 FlowHome 0x00000001053dbfd5 -[zzFlowMonitor applicationFlowMonitor_swizzling:performFetchWithCompletionHandler:] + 197
6 UIKit 0x00000001061a8c59 -[UIApplication _handleNonLaunchSpecificActions:forScene:withTransitionContext:] + 671
7 UIKit 0x00000001061ace31 __88-[UIApplication _handleApplicationLifecycleEventWithScene:transitionContext:completion:]_block_invoke + 196
8 UIKit 0x00000001061acd5e -[UIApplication _handleApplicationLifecycleEventWithScene:transitionContext:completion:] + 349
9 UIKit 0x00000001061977ba -[UIApplication scene:didUpdateWithDiff:transitionContext:completion:] + 486
10 FrontBoardServices 0x00000001088485e5 __31-[FBSSerialQueue performAsync:]_block_invoke_2 + 21
11 CoreFoundation 0x0000000105cd441c __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
12 CoreFoundation 0x0000000105cca165 __CFRunLoopDoBlocks + 341
13 CoreFoundation 0x0000000105cc9f25 __CFRunLoopRun + 2389
14 CoreFoundation 0x0000000105cc9366 CFRunLoopRunSpecific + 470
15 GraphicsServices 0x00000001091b4a3e GSEventRunModal + 161
16 UIKit 0x00000001061998c0 UIApplicationMain + 1282
17 FlowHome 0x00000001053dc22f main + 111
18 libdyld.dylib 0x0000000107593145 start + 1
19 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
您正在交换这两个方法的实现,因此self
将是您的应用程序代理,但不会有签名为-(void)applicationFlowMonitor\u swizzling:(UIApplication*)application performFetchWithCompletionHandler:(void(^)(UIBackgroundFetchResult))的方法completionHandler
,因为您从未添加该方法。该方法在zzFlowMonitor
中辞职,但其实现将是应用程序委托中定义的-(void)application:(UIApplication*)application performFetchWithCompletionHandler:(void(^)(UIBackgroundFetchResult))completionHandler
之一