動的作成クラス/swizzle class

11896 ワード


クラスの動的作成
    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));
}

 
転載先:https://www.cnblogs.com/daxueshan/p/11309970.html