From 6c9169fbde8b55c85460b6ee9e07d0774a1fbfdb Mon Sep 17 00:00:00 2001 From: springwinding Date: Wed, 13 Jan 2016 17:22:33 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AF=B9forwardInvocation:=E5=8E=9F=E5=A7=8B?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E5=81=9A=E4=B8=AA=E5=A4=8D=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 当__ASPECTS_ARE_BEING_CALLED__处理不了当前的消息时,交给原始的forwardInvocation:做消息转发处理,而 不是直接就doesNotRecognizeSelector了. --- Aspects.m | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/Aspects.m b/Aspects.m index c907066..1ea22c0 100644 --- a/Aspects.m +++ b/Aspects.m @@ -388,12 +388,18 @@ static Class aspect_hookClass(NSObject *self, NSError **error) { } static NSString *const AspectsForwardInvocationSelectorName = @"__aspects_forwardInvocation:"; +static NSString *const AspectsForwardInvocationOrignSelectorName = @"__aspects_orignForwardInvocation:"; static void aspect_swizzleForwardInvocation(Class klass) { NSCParameterAssert(klass); // If there is no method, replace will act like class_addMethod. - IMP originalImplementation = class_replaceMethod(klass, @selector(forwardInvocation:), (IMP)__ASPECTS_ARE_BEING_CALLED__, "v@:@"); + Method forwardMethod = class_getInstanceMethod(klass, @selector(forwardInvocation:)); + IMP originalImplementation = method_getImplementation(forwardMethod); if (originalImplementation) { - class_addMethod(klass, NSSelectorFromString(AspectsForwardInvocationSelectorName), originalImplementation, "v@:@"); + class_addMethod(klass, NSSelectorFromString(AspectsForwardInvocationOrignSelectorName), originalImplementation, "v@:@"); + } + IMP replaceImplementation = class_replaceMethod(klass, @selector(forwardInvocation:), (IMP)__ASPECTS_ARE_BEING_CALLED__, "v@:@"); + if (replaceImplementation) { + class_addMethod(klass, NSSelectorFromString(AspectsForwardInvocationSelectorName), replaceImplementation, "v@:@"); } AspectLog(@"Aspects: %@ is now aspect aware.", NSStringFromClass(klass)); } @@ -512,7 +518,16 @@ static void __ASPECTS_ARE_BEING_CALLED__(__unsafe_unretained NSObject *self, SEL if ([self respondsToSelector:originalForwardInvocationSEL]) { ((void( *)(id, SEL, NSInvocation *))objc_msgSend)(self, originalForwardInvocationSEL, invocation); }else { - [self doesNotRecognizeSelector:invocation.selector]; + SEL originalForwardInvocationSEL = NSSelectorFromString(AspectsForwardInvocationOrignSelectorName); + Class klass = object_getClass(invocation.target); + Method originalForwardMethod = class_getInstanceMethod(klass, originalForwardInvocationSEL); + // There is no class_removeMethod, so the best we can do is to retore the original implementation, or use a dummy. + IMP originalImplementation = method_getImplementation(originalForwardMethod); + if (originalImplementation) { + ((void( *)(id, SEL, NSInvocation *))originalImplementation)(self, selector, invocation); + }else { + [self doesNotRecognizeSelector:invocation.selector]; + } } }