iOS 运行时

作者: 星星编程 | 来源:发表于2018-04-02 17:47 被阅读35次

    1、OC的消息机制

    SEL又叫选择器,是表示一个方法的selector的指针.可以通过 Objc 编译器器命令@selector() 或者 Runtime 系统的 sel_registerName 函数来获取一个 SEL 类型的方法选择器.
    IMP实际上是一个函数指针,指向方法实现的地址.

     objc_msgSend(obj, @selector (method));//发送消息
    
     SEL selector= @selector (method);
    [self performSelector: NSSelectorFromString(@” method”)]; 
    [self performSelector:@selector( NSSelectorFromString(@” method”):) withObject:@"传入参数"];
    
    //NSString*methodName = NSStringFromSelector(selector);
    IMP methodPoint = [self methodForSelector: selector];
    //IMP methodPoint = [self instanceMethodForSelector: selector];
    methodPoint();
    

    2、方法交换

       void method_exchangeImplementations(Method m1, Method m2)
    

    首先建一个NSObject类目NSObject+ExchangeMethod,在类目中为NSObject类扩展一个my_dealloc方法用于替换系统的dealloc方法,其.m文件实现如下:

    +(void)load{
        Method m1=class_getInstanceMethod(self,NSSelectorFromString(@"dealloc"));
        Method m2=class_getInstanceMethod(self,@selector(my_dealloc));
        method_exchangeImplementations(m1,m2);
    }
    
    -(void)my_dealloc{
        NSLog(@"mydealloc");
        [self my_dealloc];
    }
    

    3、动态添加方法

    DynamicAdd *add=[DynamicAdd alloc]init];
    //[add addMethod];
    [add performSelector:@selector(addMethod)]]; //避免编译错误
    

    DynamicAdd中没有实现addMethod方法,运行时会因为找不到addMethod出现闪退.这个时候可以通过动态添加方法解决闪退问题.

    #import "DynamicAdd.h"
    #import <objc/message.h>
    
    void test(id self,SEL _cmd){
         NSLog("开发测试动态添加方法");
    }
    
    //当前对象找不到方法,回调执行该类方法,此时动态添加方法
    +(BOOL)resolveClassMethod:(SEL)sel{
           if(sel == NSSelectorFromString(@"addMethod")){
                class_addMethod(self,see,(IMP)test,@"v@:");
                return YES;
           }
        return [super resolveClassMethod:sel];
    }
    
    //如果动态添加方法失败会继续执行forwardingTargetForSelector
    
    
    - (id)forwardingTargetForSelector:(SEL)aSelector {
      
        NSString *selectorString = NSStringFromSelector(aSelector);
     
        // 将消息转发给_helper来处理;在helper里实现addMethod方法
        if ([selectorString isEqualToString:@"addMethod"]) {
            return _helper;
        }
     
        return [super forwardingTargetForSelector:aSelector];
    }
    
     
    

    4、动态添加属性

    #import<Foundation/Foundation.h>
    @interface NSObject(Property)
    @property NSString *name;
    @end
    
    
    #import "NSObject+Property.h"
    #import <objc/message.h>
    
    @implementation NSObject(Property)
    -(void)setName:(NSString *)name{
        objc_setAssociatedObject(self,"name",name,OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    
    -(NSString *)name{
        return objc_getAssociatedObject(self,"name");
    }
    @end
    

    5、获取类中的成员变量和属性

    unsigned int count;
    Ivar *ivars=class_copyIvarList([UIButton class],&count);
    for(int i=0; i<count;i++){
         Ivar ivar = ivars[i];
         NSString *name = [NSString stringWithUTF8String:ivar_getName(ivar)];
         NSString  *type = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)];
         NSLog(@"%@---%@",type,name);
    }
    

    6、消息转发

    - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
        NSMethodSignature *signature = [super methodSignatureForSelector:aSelector];
     
        if (!signature) {
            if ([Helper instancesRespondToSelector:aSelector]) {
                signature = [Helper instanceMethodSignatureForSelector:aSelector];
            }
        }
     
        return signature;
    }
     
    - (void)forwardInvocation:(NSInvocation *)anInvocation {
        if ([Helper instancesRespondToSelector:anInvocation.selector]) {
            [anInvocation invokeWithTarget:_helper];
        }
    }
    

    相关文章

      网友评论

        本文标题:iOS 运行时

        本文链接:https://www.haomeiwen.com/subject/bjdthftx.html