zoukankan      html  css  js  c++  java
  • 动态创建类/ swizzle class

    动态创建类

        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));
    }
  • 相关阅读:
    Linux基础之-正则表达式(grep,sed,awk)
    Linux基础之-利用shell脚本实现自动监控系统服务
    Linux基础之-网络配置,主机名设置,ssh登陆,scp传输
    Linux基础之-Bash命令优先级
    Linux基础之命令练习Day7-nginx,nfs
    Linux基础之命令练习Day4-fdisk,mkfs,mlabel,mount,umount,mkswap,swapon,dd,top,free,ps,kill,rpm,yum,make
    Linux基础之命令练习Day3-文件管理:cat,tar,gzip,vim,ln
    Linux基础之命令练习Day2-useradd(mod,del),groupadd(mod,del),chmod,chown,
    按二次返回键退出
    注册用户倒计时
  • 原文地址:https://www.cnblogs.com/daxueshan/p/11309970.html
Copyright © 2011-2022 走看看