动态创建类
Class subclass = objc_allocateClassPair(baseClass, subclassName, 0);//生成,指定父类 //添加方法,变量...一些操作
//swizzle消息转发机制
RACSwizzleForwardInvocation(subclass);
RACSwizzleRespondsToSelector(subclass);
//改变class
RACSwizzleGetClass(subclass, statedClass);
RACSwizzleGetClass(object_getClass(subclass), statedClass);
RACSwizzleMethodSignatureForSelector(subclass);
objc_registerClassPair(subclass); //注册 object_setClass(self, subclass);//设置isa指针
SwizzleGetClass
static void RACSwizzleGetClass(Class class, Class statedClass) { SEL selector = @selector(class); Method method = class_getInstanceMethod(class, selector); IMP newIMP = imp_implementationWithBlock(^(id self) { return statedClass; }); class_replaceMethod(class, selector, newIMP, method_getTypeEncoding(method)); }
SwizzleForwardInvocation
static BOOL RACForwardInvocation(id self, NSInvocation *invocation) { SEL aliasSelector = RACAliasForSelector(invocation.selector); RACSubject *subject = objc_getAssociatedObject(self, aliasSelector); Class class = object_getClass(invocation.target); BOOL respondsToAlias = [class instancesRespondToSelector:aliasSelector]; if (respondsToAlias) { invocation.selector = aliasSelector; [invocation invoke]; } if (subject == nil) return respondsToAlias; [subject sendNext:invocation.rac_argumentsTuple]; return YES; } static void RACSwizzleForwardInvocation(Class class) { SEL forwardInvocationSEL = @selector(forwardInvocation:); Method forwardInvocationMethod = class_getInstanceMethod(class, forwardInvocationSEL); // 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; if (originalForwardInvocation == NULL) { [self doesNotRecognizeSelector:invocation.selector]; } else { originalForwardInvocation(self, forwardInvocationSEL, invocation); } }; class_replaceMethod(class, forwardInvocationSEL, imp_implementationWithBlock(newForwardInvocation), "v@:@"); }
SwizzleMethodSignatureForSelector
static void RACSwizzleMethodSignatureForSelector(Class class) { IMP newIMP = imp_implementationWithBlock(^(id self, SEL selector) { // Don't send the -class message to the receiver because we've changed // that to return the original class. Class actualClass = object_getClass(self); Method method = class_getInstanceMethod(actualClass, selector); if (method == NULL) { // Messages that the original class dynamically implements fall // here. // // Call the original class' -methodSignatureForSelector:. struct objc_super target = { .super_class = class_getSuperclass(class), .receiver = self, }; NSMethodSignature * (*messageSend)(struct objc_super *, SEL, SEL) = (__typeof__(messageSend))objc_msgSendSuper; return messageSend(&target, @selector(methodSignatureForSelector:), selector); } char const *encoding = method_getTypeEncoding(method); return [NSMethodSignature signatureWithObjCTypes:encoding]; }); SEL selector = @selector(methodSignatureForSelector:); Method methodSignatureForSelectorMethod = class_getInstanceMethod(class, selector); class_replaceMethod(class, selector, newIMP, method_getTypeEncoding(methodSignatureForSelectorMethod)); }
SwizzleRespondsToSelector
static void RACSwizzleRespondsToSelector(Class class) { SEL respondsToSelectorSEL = @selector(respondsToSelector:); // Preserve existing implementation of -respondsToSelector:. Method respondsToSelectorMethod = class_getInstanceMethod(class, respondsToSelectorSEL); BOOL (*originalRespondsToSelector)(id, SEL, SEL) = (__typeof__(originalRespondsToSelector))method_getImplementation(respondsToSelectorMethod); // Set up a new version of -respondsToSelector: that returns YES for methods // added by -rac_signalForSelector:. // // If the selector has a method defined on the receiver's actual class, and // if that method's implementation is _objc_msgForward, then returns whether // the instance has a signal for the selector. // Otherwise, call the original -respondsToSelector:. id newRespondsToSelector = ^ BOOL (id self, SEL selector) { Method method = rac_getImmediateInstanceMethod(class, selector); if (method != NULL && method_getImplementation(method) == _objc_msgForward) { SEL aliasSelector = RACAliasForSelector(selector); if (objc_getAssociatedObject(self, aliasSelector) != nil) return YES; } return originalRespondsToSelector(self, respondsToSelectorSEL, selector); }; class_replaceMethod(class, respondsToSelectorSEL, imp_implementationWithBlock(newRespondsToSelector), method_getTypeEncoding(respondsToSelectorMethod)); }