//这个地方是基于当前self类创建了一个新类型,有很多hook的逻辑都放在这个类型中 //具体逻辑在RACSwizzleClass函数中再分析 Class class = RACSwizzleClass(self); NSCAssert(class != nil, @"Could not swizzle class of %@", self);
//targetMethod是"viewDidApear"这个Selector的方法对象 Method targetMethod = class_getInstanceMethod(class, selector); if (targetMethod == NULL) { //按照现有逻辑,这里应该是走不到的,先不去看它 const char *typeEncoding; if (protocol == NULL) { typeEncoding = RACSignatureForUndefinedSelector(selector); } else { // Look for the selector as an optional instance method. struct objc_method_description methodDescription = protocol_getMethodDescription(protocol, selector, NO, YES);
if (methodDescription.name == NULL) { // Then fall back to looking for a required //instance method. methodDescription = protocol_getMethodDescription(protocol , selector , YES , YES); NSCAssert(methodDescription.name != NULL , @"Selector %@ does not exist in <%s>" ,NSStringFromSelector(selector) , protocol_getName(protocol)); }
typeEncoding = methodDescription.types; }
RACCheckTypeEncoding(typeEncoding);
// Define the selector to call -forwardInvocation:. if (!class_addMethod(class, selector, _objc_msgForward, typeEncoding)) { NSDictionary *userInfo = @{ NSLocalizedDescriptionKey: [NSString stringWithFormat: NSLocalizedString( @"A race condition occurred implementing %@ on class %@" , nil) ,NSStringFromSelector(selector) , class], NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString(@"Invoke -rac_signalForSelector: again to override the implementation.", nil) };
return [RACSignal error:[NSError errorWithDomain: RACSelectorSignalErrorDomain code:RACSelectorSignalErrorMethodSwizzlingRace userInfo:userInfo]]; } //_objc_msgForward是消息进行转发的开始,这里主要是判断原始的 //方法对象有没有被hook成_objc_msgForward,因为下面要开始进行方法实现的替换了 } else if (method_getImplementation(targetMethod) != _objc_msgForward) { // Make a method alias for the existing //method implementation. const char *typeEncoding = method_getTypeEncoding(targetMethod); RACCheckTypeEncoding(typeEncoding); //class_addMethod只是在当前类型对象(不会去基类中查找)中 //去找有没有aliasSelector的方法,如果有就直接返回原来的方法实现 //如果没有就添加一个 BOOL addedAlias __attribute__((unused)) = class_addMethod(class, aliasSelector, method_getImplementation(targetMethod), typeEncoding); NSCAssert(addedAlias, @"Original implementation for %@ is already copied to %@ on %@", NSStringFromSelector(selector), NSStringFromSelector(aliasSelector), class); // Redefine the selector to call -forwardInvocation:. // 这里相当于对原始方法进行方法实现的替换, //只要调用原始方法,直接会开始方法转发的过程 class_replaceMethod(class , selector , _objc_msgForward, method_getTypeEncoding(targetMethod)); }
static Class RACSwizzleClass(NSObject *self) { //self.class和object_getClass返回的都是当前实例的类对象,好像没什么区别??? Class statedClass = self.class; Class baseClass = object_getClass(self);
// The "known dynamic subclass" is the subclass generated by RAC. // It's stored as an associated object on every instance that's already // been swizzled, so that even if something else swizzles the class of // this instance, we can still access the RAC generated subclass. //这里官方说明了子类的用途,如果有其他地方swizzle了当前类对象,那也不太影响RAC自己的逻辑 //因为它所有的信息都保存在自己创建的子类中。 Class knownDynamicSubclass = objc_getAssociatedObject(self, RACSubclassAssociationKey); if (knownDynamicSubclass != Nil) return knownDynamicSubclass;
// Preserve any existing implementation of -forwardInvocation:. void (*originalForwardInvocation)(id, SEL, NSInvocation *) = NULL; if (forwardInvocationMethod != NULL) { originalForwardInvocation = (__typeof__(originalForwardInvocation))method_getImplementation( forwardInvocationMethod); }
// Set up a new version of -forwardInvocation:. // // If the selector has been passed to -rac_signalForSelector:, invoke // the aliased method, and forward the arguments to any attached signals. // // If the selector has not been passed to -rac_signalForSelector:, // invoke any existing implementation of -forwardInvocation:. If there // was no existing implementation, throw an unrecognized selector // exception. id newForwardInvocation = ^(id self, NSInvocation *invocation) { BOOL matched = RACForwardInvocation(self, invocation); if (matched) return;
static void aspect_swizzleForwardInvocation(Class klass) { NSCParameterAssert(klass); // If there is no method, replace will act like class_addMethod. //将forwardInvocation方法实现替换成了__ASPECTS_ARE_BEING_CALLED__ IMP originalImplementation = class_replaceMethod(klass ,@selector(forwardInvocation:) ,(IMP)__ASPECTS_ARE_BEING_CALLED__ ,"v@:@"); if (originalImplementation) { //alias的forwardInvocation换成了原始实现 class_addMethod(klass, NSSelectorFromString(AspectsForwardInvocationSelectorName), originalImplementation, "v@:@"); } AspectLog(@"Aspects: %@ is now aspect aware.", NSStringFromClass(klass)); }
通过上面的分析,如果说在BusinessViewController中没有调用super的方法,那么不会引起死循环的,因为不会触发UIViewController类对象的Hook流程。并且当触发了死循环之后,会发现RAC订阅的业务层的回调和BusinessViewController的A方法中除了Super那一句,剩下的业务代码也没有被执行。另外,RAC这种Hook相对来说会更安全一些(并不是说Aspects就没有Hook Class 的情况,只是当前是这样):它完全子类化了业务类,并且将Hook全都保留在了新建的子类型中,对其他类型包括原始业务类型没有干扰并且这种Hook只针对了某个具体的实例对象,其他势力对象如果没有通过调用rac_singalForSelector并不会受到任何影响。