• 运行时c函数


    // 修改isa,本质就是改变当前对象的类名
        object_setClass(self, [XMGKVONotifying_Person class]);


    // self动态添加关联
        // id object:给哪个对象添加关联属性
        // key:属性名
        // value:关联值
        //objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
        objc_setAssociatedObject(self, @"observer", observer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

    // self获取关联
        //objc_getAssociatedObject(id object, const void *key)
        id observer = objc_getAssociatedObject(self, @"observer");


     默认情况下,如果是以[object message]的方式调用方法,如果object无法响应message消息时,编译器会报错。但如果是以perform…的形式来调用,则需要等到运行时才能确定object是否能接收message消息。如果不能,则程序崩溃。

    通常,当我们不能确定一个对象是否能接收某个消息时,会先调用respondsToSelector:来判断一下。如下代码所示:

    if ([self respondsToSelector:@selector(method)]) {
        [self performSelector:@selector(method)];
    }

    摘录其它博客:

    @implementation HYBMethodLearn
    
    - (int)testInstanceMethod:(NSString *)name andValue:(NSNumber *)value {
      NSLog(@"%@", name);
      return value.intValue;
    }
    
    - (void)getMethods {
      unsigned int outCount = 0;
      Method *methodList = class_copyMethodList(self.class, &outCount);
      
      for (unsigned int i = 0; i < outCount; ++i) {
        Method method = methodList[i];
        
        SEL methodName = method_getName(method);
        NSLog(@"方法名:%@", NSStringFromSelector(methodName));
        
        // 获取方法的参数类型
        unsigned int argumentsCount = method_getNumberOfArguments(method);
        char argName[512] = {};
        for (unsigned int j = 0; j < argumentsCount; ++j) {
          method_getArgumentType(method, j, argName, 512);
          
          NSLog(@"第%u个参数类型为:%s", j, argName);
          memset(argName, '', strlen(argName));
        }
        
        char returnType[512] = {};
        method_getReturnType(method, returnType, 512);
        NSLog(@"返回值类型:%s", returnType);
        
        // type encoding
        NSLog(@"TypeEncoding: %s", method_getTypeEncoding(method));
      }
      
      free(methodList);
    }
    
    
    + (void)test {
      HYBMethodLearn *m = [[HYBMethodLearn alloc] init];
    //  [m getMethods];
      
      ((void (*)(id, SEL))objc_msgSend)((id)m, @selector(getMethods));
      
      // 这就是为什么有四个参数的原因
      int returnValue = ((int (*)(id, SEL, NSString *, NSNumber *))
                         objc_msgSend)((id)m,
                                       @selector(testInstanceMethod:andValue:),
                                       @"标哥的技术博客",
                                       @100);
      NSLog(@"return value is %d", returnValue);
      
      // 获取方法
      Method method = class_getInstanceMethod([self class], @selector(testInstanceMethod:andValue:));
      
      // 调用函数
      returnValue = ((int (*)(id, Method, NSString *, NSNumber *))method_invoke)((id)m, method, @"测试使用method_invoke", @11);
      NSLog(@"call return vlaue is %d", returnValue);
    }

    给NSMutableArray添加分类

    #import "NSMutableArray+Swizzling.h"
    #import <objc/runtime.h>
    #import <objc/message.h>
    
    @implementation NSMutableArray (Swizzling)
    +(void)load
    {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            
            //NSMutableArray ---->__NSArrayM
            Method method=class_getInstanceMethod(objc_getClass("__NSArrayM"), @selector(objectAtIndex:));
            
            Method method2=class_getInstanceMethod(objc_getClass("__NSArrayM"), @selector(fdc_objectAtIndex:));
            
            method_exchangeImplementations(method, method2);
        });
    }
    -(id)fdc_objectAtIndex:(NSInteger)index
    {
    //    NSLog(@"%s",__func__);  千万别加上这句  不然有bug
        if (self.count == 0) {
            NSLog(@"%s can't get any object from an empty array", __FUNCTION__);
            return nil;
        }
        
        if (index > self.count) {
            NSLog(@"%s index out of bounds in array", __FUNCTION__);
            return nil;
        }
        return [self fdc_objectAtIndex:index];
    }
    @end

        Student *obj=[[Student alloc]init];
        
        NSLog(@"instance         :%p", obj);
        NSLog(@"---------------------------------------------");
        NSLog(@"class            :%p", object_getClass(obj));
        NSLog(@"meta class       :%p", object_getClass(object_getClass(obj)));
        NSLog(@"root meta        :%p", object_getClass(object_getClass(object_getClass(obj))));
        NSLog(@"root meta's meta :%p", object_getClass(object_getClass(object_getClass(object_getClass(obj)))));
        NSLog(@"---------------------------------------------");
        NSLog(@"class            :%p", [obj class]);
        NSLog(@"meta class       :%p", [[obj class] class]);
        NSLog(@"root meta        :%p", [[[obj class] class] class]);
        NSLog(@"root meta's meta :%p", [[[[obj class] class] class] class]);
    2016-07-14 10:24:05.074 测试[1145:46819] instance         :0x7fed2276d9c0
    2016-07-14 10:24:05.075 测试[1145:46819] ---------------------------------------------
    2016-07-14 10:24:05.075 测试[1145:46819] class            :0x101417060
    2016-07-14 10:24:05.075 测试[1145:46819] meta class       :0x101417038
    2016-07-14 10:24:05.076 测试[1145:46819] root meta        :0x101c75198
    2016-07-14 10:24:05.076 测试[1145:46819] root meta's meta :0x101c75198
    2016-07-14 10:24:05.076 测试[1145:46819] ---------------------------------------------
    2016-07-14 10:24:05.076 测试[1145:46819] class            :0x101417060
    2016-07-14 10:24:05.076 测试[1145:46819] meta class       :0x101417060
    2016-07-14 10:24:05.077 测试[1145:46819] root meta        :0x101417060
    2016-07-14 10:24:05.077 测试[1145:46819] root meta's meta :0x101417060

    类簇

    类簇的概念:一个父类有好多子类,父类在返回自身对象的时候,向外界隐藏各种细节,根据不同的需要返回的其实是不同的子类对象,这其实就是抽象类工厂的实现思路,iOS最典型的就是NSNumber。

    NSNumber,NSArray,NSDictionary、NSString、NSTimer…这说明大多数的OC类都是类簇实现的;

        NSNumber *intNum = [NSNumber numberWithInt:1];
        NSNumber *boolNum = [NSNumber numberWithBool:YES];
        NSLog(@"intNum :%@", [intNum class]);
        NSLog(@"boolNum:%@", [boolNum class]);
        NSLog(@"Superclass:%@", class_getSuperclass([boolNum class]));
        NSLog(@"Superclass:%@", class_getSuperclass([intNum class]));
    2016-07-14 10:30:21.166 测试[1179:51674] intNum :__NSCFNumber
    2016-07-14 10:30:21.167 测试[1179:51674] boolNum:__NSCFBoolean
    2016-07-14 10:30:21.167 测试[1179:51674] Superclass:NSNumber
    2016-07-14 10:30:21.167 测试[1179:51674] Superclass:NSNumber
  • 相关阅读:
    JS数组存储(两个数组相等,一个改变,另一个跟着改变)
    图片404加载失败后如何处理
    为什么重写equals方法,还必须要重写hashcode方法
    Java中HashMap和TreeMap的区别深入理解
    java中String数组和List的互相转化
    log4j重复打印的解决方法
    mysql 允许在唯一索引的字段中出现多个null值
    elasticsearch 常见查询及聚合的JAVA API
    A记录(主机名解析)、CNAME(别名解析)和URL转发(域名转发)
    域名解析中的cname解析和显性URL跳转和隐性URL跳转三者有什么区别
  • 原文地址:https://www.cnblogs.com/jingdizhiwa/p/5666417.html
Copyright © 2020-2023  润新知