RunTime小结黑魔法

(一)拦截交换系统设置图片的方法

#import <UIKit/UIKit.h>

@interface UIImage (MyImage)

+ (UIImage *)theNewImageName:(NSString *)name;

@end
#import "UIImage+MyImage.h"
#import <objc/runtime.h>

@implementation UIImage (MyImage)

+ (void)load
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        //交换设置图片的方法
#pragma mark ---如果需要交换的方法是 “-”实例方法 就用 class_getInstanceMethod, ,如果是“+”类方法 就用class_getClassMethod
        Method originMethod = class_getClassMethod(self, @selector(imageNamed:));
        Method customMethod = class_getClassMethod(self, @selector(theNewImageName:));
        method_exchangeImplementations(originMethod, customMethod);

    });
}

+ (UIImage *)theNewImageName:(NSString *)name
{
    NSString *theName = [NSString stringWithFormat:@"new_%@",name];
    return [UIImage theNewImageName:theName];
}

@end

(二)给系统类添加属性

#import <Foundation/Foundation.h>

@interface NSDictionary (MyDictionary)

//给字典类增加属性
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *gender;

@end
#import "NSDictionary+MyDictionary.h"
#import <objc/runtime.h>

@implementation NSDictionary (MyDictionary)

/**
 在延展里面都
 *  object:要关联的对象
 key:要关联的属性的key值
 value:要关联的属性
 polocy:是枚举类型
 enum {
 OBJC_ASSOCIATION_ASSIGN = 0, 所修饰的属性对象是弱引用的
 OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, 强引用,非线程安全
 OBJC_ASSOCIATION_COPY_NONATOMIC = 3, 指定相关的复制对象,非线程安全
 OBJC_ASSOCIATION_RETAIN = 01401, 指定关联的对象的强引用,线程安全 默认atomic
 OBJC_ASSOCIATION_COPY = 01403 指定相关的复制对象 ,默认是atomic
 };
 */

- (void)setName:(NSString *)name
{
    objc_setAssociatedObject(self, @selector(name), name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSString *)name
{
  return objc_getAssociatedObject(self, @selector(name));
}

- (void)setGender:(NSString *)gender
{
    objc_setAssociatedObject(self, @selector(gender), gender, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSString *)gender
{
    return objc_getAssociatedObject(self, @selector(gender));
}

@end

(三)使用RunTime给类属性归档

#import <Foundation/Foundation.h>

@interface Person : NSObject

- (void)eat;
- (void)drink;

@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *gender;
@property (nonatomic, assign) NSInteger age;

@end
//归档
- (void)encodeWithCoder:(NSCoder *)aCoder
{
    unsigned int count = 0;
    //1.获得变量列表数组
    Ivar *ivarList = class_copyIvarList([self class], &count);
    //2.循环
    for (int i = 0; i < count; i++) {
        //3.获取变量名
        Ivar ivar = ivarList[i];
        //4.将c语言字符串转换成 oc字符串
        NSString *ivarString = [NSString stringWithUTF8String:ivar_getName(ivar)];
        //5.归档
        [aCoder encodeObject:[self valueForKey:ivarString] forKey:ivarString];
    }

}

//反归档
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
    self = [super init];
    if (self) {
        unsigned int count = 0;
        Ivar *ivarList = class_copyIvarList([self class], &count);
        for (int i = 0; i < count; i++) {
            Ivar ivar = ivarList[i];
            NSString *ivarString = [NSString stringWithUTF8String:ivar_getName(ivar)];
            //反归档
            [self setValue:[aDecoder decodeObjectForKey:ivarString] forKey:ivarString];
        }
    }
    return self;
}
时间: 2024-12-19 01:32:21

RunTime小结黑魔法的相关文章

runloop和runtime小结

runloop运行循环 1:是个死循环,主线程默认开启,子线程不开启 2:保证程序不退出 3:监听事件,应用场景 1:定时器,时钟,NSTimer,CADisplayLink 2:监听网络端口数据的接收和发送情况,socket开发 iOS 中所有的事件监听全部由运行循环负责 主线程的 RunLoop 在应用启动的时候就会自动创建 其他线程则需要在该线程下自己启动 不能自己创建 RunLoop RunLoop 并不是线程安全的,所以需要避免在其他线程上调用当前线程的 RunLoop RunLoop

runtime 第四部分method swizzling

接上一篇 http://www.cnblogs.com/ddavidXu/p/5924597.html 转载来源http://www.jianshu.com/p/6b905584f536 http://southpeak.github.io/2014/10/30/objective-c-runtime-2/ runtime的黑魔法,就是可以实现交换两个方法的实现,这就意味着我们可以修改系统的方法实现. 栗子:当UIViewController及其子类的对象调用viewWillAppear时,都会

runtime之消息转发

前言 在上一篇文章中我们初尝了runtime的黑魔法,可以在程序编译阶段就获取到成员变量的名字,特性以及动态的给对象增加属性等等,在接下来中我们进一步了解OC的消息发送机制.如果之前没接触过runtime的同学建议先看看:上一篇<runtime之玩转成员变量> OC的消息发送机制是早有耳闻,鉴于自己一直觉得是很底层的东西需要花大量的时候去学习研究它所以一直都是蠢蠢欲动.同样不做过多铺垫,直接切入吧.当我们使用OC对象调用一个方法的时候,比如这样:[lisi  sayHello];  程序运行的

iOS书写高质量代码之耦合的处理

原创 2016-12-26 MrPeak MrPeak杂货铺 耦合是每个程序员都必须面对的话题,也是容易被忽视的存在,怎么处理耦合关系到我们最后的代码质量.今天Peak君和大家聊聊耦合这个基本功话题,一起捋一捋iOS代码中处理耦合的种种方式及差异. 简化场景 耦合的话题可大可小,但原理都是相通的.为了方便讨论,我们先将场景进行抽象和简化,只讨论两个类之间的耦合. 假设我们有个类Person,需要喝水,根据职责划分,我们需要另一个类Cup来完成喝水的动作,代码如下: //Person.h @int

iOS书写高质量代码之耦合的处理 干货!

iOS书写高质量代码之耦合的处理 耦合是每个程序员都必须面对的话题,也是容易被忽视的存在,怎么处理耦合关系到我们最后的代码质量.今天Peak君和大家聊聊耦合这个基本功话题,一起捋一捋iOS代码中处理耦合的种种方式及差异. 简化场景 耦合的话题可大可小,但原理都是相通的.为了方便讨论,我们先将场景进行抽象和简化,只讨论两个类之间的耦合. 假设我们有个类Person,需要喝水,根据职责划分,我们需要另一个类Cup来完成喝水的动作,代码如下: 1 2 3 4 5 6 7 8 9 //Person.h

iOS runtime探究(四): 从runtiem开始实践Category添加属性与黑魔法method swizzling

你要知道的runtime都在这里 转载请注明出处 http://blog.csdn.net/u014205968/article/details/67639335 本文主要讲解runtime相关知识,从原理到实践,由于包含内容过多分为以下五篇文章详细讲解,可自行选择需要了解的方向: 从runtime开始: 理解面向对象的类到面向过程的结构体 从runtime开始: 深入理解OC消息转发机制 从runtime开始: 理解OC的属性property 从runtime开始: 实践Category添加属

iOS Runtime-OC黑魔法

在项目中经常会发现一些奇怪的功能.不太能找的到代码的出处,但却实现了功能,很可能这是实用了运行时的东西. 运行时即Runtime .使用起来很有意思.多了解也有助于对oc的理解. 这里我有写个关于Runtime 的demo     https://github.com/WangFeiF/WFRuntime 在这个博客里只是demo的摘要.详细可以下载demo.查看源码. // // ViewController.m // Runtime // // Created by 王飞 on 16/5/8

runtime总结二之消息机制(包括消息转发,消息交换的黑魔法)

runtime的消息机制 前面提到过编译器最终会把我们的消息发送转化为函数调用 消息发送 [object sendMassage] 首先编译器会在运行时将上面的例子转化为objc_msgSend(obj,@selector(sendMassage))这个函数,转换的时候除了方法本身的参数之外,还有两个隐藏的参数一个是id类型的,代表对象的类型,还是一个是SEL类型的,是函数对应的方法的编号,接下来就会按照下面的流程来调用这个方法 通过obj的isa指针找到其所对应的类. 通过SEL先去类的cac

ObjC Runtime 黑魔法 — Method Swizzling

适用情境 项目中大量控制器需要在载入时进行日志统计或进行类似的处理.如果直接往所有控制器中进行代码编写,会产生大量的重复的代码,降低了代码后期的可读性,不利于维护.由于所有部分的逻辑代码相同,针对这种情况,以切面编程(AOP)思想为导向,利用 Method Swizzling 能极大降低这种(日志统计)非主要逻辑代码与控制器的耦合度. AOP概念详解(摘自百度百科) 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理