美文网首页
iOS runtime使用

iOS runtime使用

作者: 罗马危机 | 来源:发表于2018-09-12 09:45 被阅读0次

    1. 发送消息

    objc_msgSend(obj, @selector(func));   调用实例方法

    objc_msgSend([Obj class], @selector(func)); 调用类方法

    2.交换方法

    // 加载内存时调用

    + (void)load

    {

      // 获取 ImageOriginalWithStrName: 方法

    MethodmyImageName =class_getClassMethod(self,@selector(myImageNamed:));

      // 获取 imageName 方法

    MethodimageName =class_getClassMethod(self,@selector(imageNamed:));

      // 交换方法地址, 相当于交换实现

      method_exchangeImplementations(myImageName, imageName);

    }

    + (id)myImageNamed:(NSString*)name

    {

      UIImage *image = [[self  myImageName:name] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];

    if(image ==nil) {

    NSLog(@"我自己的操作");

      }

    returnimage;

    }

    3.动态添加方法

    [self performSelector:@selector(test)];

    void test (id self, SEL sel){

      NSLog(@"--- ");

    }

    /*

     当一个对象调用未实现的方法,会调用+ (BOOL)resolveInstanceMethod:(SEL)sel

     这个方法处理,并且会把这个对应方法列表传过来

     所以动态添加方法, 我们可以在这里做判断, 为我们未实现的方法动态添加自己的方法.

     */

    +(BOOL)resolveInstanceMethod:(SEL)sel{

     if (sel == NSSelectorFromString(@"test1")) {

     // <#__unsafe_unretained Class cls#> 参数1 给哪个类添加方法

     // <#SEL name#>  参数2 添加哪个方法

     // <#IMP imp#> 参数3 添加方法函数实现 (函数地址)

     // <#const char *types#> 参数4 函数的类型 (返回值 + 参数类型) v:void @:对象-> self :表示SEL -> _cmd

     class_addMethod(self, sel, (IMP)test1, "v@:@");

     return YES;

     }

     return [super resolveInstanceMethod:sel];

    }

    4.给分类添加属性

    @interface NSObject (ObjName)

    @property (nonatomic, strong) NSString *name; // 添加一个name属性

    @end

    #import 

    static const char *key = "name";

    @implementation NSObject (ObjName)

    - (NSString *)name{

    // 根据关联的key,获取关联的值

     return objc_getAssociatedObject(self, key);

    }

    - (void)setName:(NSString *)name{

     // 参数1 id object 给那个对象添加关联

     // 参数2 const void *key 关联的key 值,通过这个key 值获取

     // 参数3 id value 关联的value

     // 参数4 objc_AssociationPolicy policy 关联的策略

     objc_setAssociatedObject(self, key, name, OBJC_ASSOCIATION_COPY_NONATOMIC);

    }

    @end

    5.模型转换

    - (instancetype)initWithDict:(NSDictionary *)dict

    {

     self = [super init];

     if (self)

     {

     // 获取类的属性及属性对应的类型

     NSMutableArray *keys = [NSMutableArray array];

     unsigned int outCount;

     objc_property_t *properties = class_copyPropertyList([self class], &outCount);

     for (int i = 0; i < outCount; i ++)

     {

     objc_property_t property = properties[i];

     // 通过property_getName函数获得属性的名字

     NSString *propertyName = [NSStringstringWithCString:property_getName(property) encoding:NSUTF8StringEncoding];

     [keys addObject:propertyName];

     }

     // 立即释放properties指向的内存

     free(properties);

     // 根据类型给属性赋值

     NSLog(@"+++%@",keys);

     for (NSString *key in keys)

     {

     id value = [dict valueForKey:key];

     if (value == nil)

     {

     continue;

     }

     [self setValue:value forKey:key];

     }

     }

     return self;

    }

    6.归档、解档

    //归档- (void)encodeWithCoder:(NSCoder*)aCoder

    {    unsigned int count = 0;

        Ivar* ivars = class_copyIvarList([self class], &count);

        for (int i = 0; i < count; i++) { Ivar ivar = ivars[i]; const char* name = ivar_getName(ivar); NSString* key = [NSString stringWithUTF8String:name];

            [aCoder encodeObject:[self valueForKey:key] forKey :key];

        }

        free(ivars);

    }//解档- (id)initWithCoder:(NSCoder*)aDecoder

    {    if (self == [superinit]) { unsigned int count = 0; Ivar* ivars = class_copyIvarList([selfclass], &count); for (int i = 0; i < count; i++) { Ivar ivar = ivars[i]; const char* name = ivar_getName(ivar); NSString* key = [NSStringstringWithUTF8String:name]; id value =  [aDecoder decodeObjectForKey:key];//根据key拿到value [self setValue:value forKey:key];//KVC赋值 } free(ivars);    }return self;

    }

    相关文章

      网友评论

          本文标题:iOS runtime使用

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