www.88pt88.com兴许也能够给别人一些经验,调换四个

2019-09-17 20:25栏目:大奖888官网登录
TAG:

打印结果如下:

三、获得叁个类的享有成员变量

案例1:获取Person类中持有成员变量的名字和系列

内需运用的主意 <objc/runtime.h>

  • 获得某个类的具备成员变量(outCount 会重回成员变量的总额)参数:
    1、哪个类
    2、放二个接收值的地址,用来存放在属性的个数
    3、重回值:贮存全部得到到的性质,通过上面三个方法可以调有名字和种类
Ivar *class_copyIvarList(Class cls , unsigned int *outCount)
  • 收获成员变量的名字
    const char *ivar_getName(Ivar v)
  • 获得成员变量的项目
const char *ivar_getTypeEndcoding(Ivar v)

案例2:拦截系统方法

急需:比如iOS6 晋级 iOS7 后需求版本适配,依照差异连串采纳不一致体裁图片(拟物化和扁平化),怎样通过不去手动一个个退换每一种UIImage的imageNamed:方法就足以完成为该方法中加入版本判别语句?

步骤:
1、为UIImage建贰个分类(UIImage+Category)
2、在分拣中贯彻叁个自定义方法,方法中写要在系统方法中加入的讲话,举个例子版本推断

+ (UIImage *)xh_imageNamed:(NSString *)name {
    double version = [[UIDevice currentDevice].systemVersion doubleValue];
    if (version >= 7.0) {
        // 如果系统版本是7.0以上,使用另外一套文件名结尾是‘_os7’的扁平化图片
        name = [name stringByAppendingString:@"_os7"];
    }
    return [UIImage xh_imageNamed:name];
}

3、分类中重写UIImage的load方法,达成格局的沟通(只要能让其试行三回艺术交流语句,load再适合不过了)

+ (void)load {
    // 获取两个类的类方法
    Method m1 = class_getClassMethod([UIImage class], @selector(imageNamed:));
    Method m2 = class_getClassMethod([UIImage class], @selector(xh_imageNamed:));
    // 开始交换方法实现
    method_exchangeImplementations(m1, m2);
}

瞩目:自定义方法中最后必须要再调用一下系统的艺术,让其有加载图片的机能,然而出于措施交流,系统的格局名已经成为了我们自定义的方法名(有一点绕,正是用我们的名字能调用系统的法子,用系统的名字能调用大家的办法),那就落实了系统方法的阻挠!
应用上述思路,我们仍是可以给 NSObject 加多分类,总括创设了不怎么个指标,给调整器增添分类,总计有开创了稍稍个调整器,极度是公司须要总变的时候,在有些原本控件或模块上添加一个职能,提出选取该措施!

在viewcontroller中引用,导入<objc/runtime.h>,通过runtime 达成格局交流,类格局用class_getClassMethod,对象方法用class_getInstanceMethod

案例2:拦截系统方法

急需:举例手提式有线电话机尺寸须求版本适配,依照不相同种类选择差异体制图片(拟物化和扁平化),怎么着通过不去手动叁个个修改每一种UIImage的imageNamed:方法就足以兑现为该方式中参预版本推断语句?

手续:1、为UIImage建二个分类(UIImage+Category)。
2、在分拣中完成二个自定义方法,方法中写要在系统方法中到场的讲话,比方版本决断。
3、分类中重写UIImage的load方法,实现情势的沟通(只要能让其实践二回艺术交流语句,load再合适不过了)。

#import "UIImage+Category.h"
#import <objc/runtime.h>

#define iPhone4 (CGSizeEqualToSize(CGSizeMake(320, 480), [UIScreen mainScreen].bounds.size))
#define iPhone5 (CGSizeEqualToSize(CGSizeMake(320, 568), [UIScreen mainScreen].bounds.size))
#define iPhone6 (CGSizeEqualToSize(CGSizeMake(375, 667), [UIScreen mainScreen].bounds.size))
#define iPhone6plus (CGSizeEqualToSize(CGSizeMake(414, 736), [UIScreen mainScreen].bounds.size))

@implementation UIImage (Category)
+ (void)load {
    // 获取两个类的类方法
    Method m1 = class_getClassMethod([UIImage class], @selector(imageNamed:));
    Method m2 = class_getClassMethod([UIImage class], @selector(zdy_imageNamed:));
    // 开始交换方法实现
    method_exchangeImplementations(m1, m2);
}

+ (UIImage *)zdy_imageNamed:(NSString *)name {

    if (iPhone6plus) {
        // 如果苹果尺寸是6p,使用另外一套文件名结尾是‘_os7’的扁平化图片
        name = [name stringByAppendingString:@"_10"];
    }

    return [UIImage zdy_imageNamed:name];
}

在调整器中调用,会发觉在6p上和6上,彰显的图纸不等同。

留意:自定义方法中最后绝对要再调用一下系统的办法,让其有加载图片的功能,不过出于措施交流,系统的点子名已经成为了大家自定义的主意名(有一点点绕,正是用大家的名字能调用系统的章程,用系统的名字能调用大家的措施),那就落到实处了系统方法的阻碍!
行使上述思路,大家仍是可以给 NSObject 加多分类,总计创立了多少个目的,给调节器增添分类,计算有创立了稍稍个调节器,特别是集团需求总变的时候,在有些原本控件或模块上增加一个效果,提议选择该措施!

案例1:方法简便的置换

创设一个Person类,类中落实以下多个类格局,并在.h 文件中宣称

+ (void)run {
    NSLog(@"跑");
}

+ (void)study {
    NSLog(@"学习");
}

调节器中调用,则先打字与印刷跑,后打字与印刷学习

[Person run];
[Person study];

下边通过runtime 完成格局沟通,类方式用class_getClassMethod ,对象方法用class_getInstanceMethod

// 获取两个类的类方法
Method m1 = class_getClassMethod([Person class], @selector(run));
Method m2 = class_getClassMethod([Person class], @selector(study));
// 开始交换方法实现
method_exchangeImplementations(m1, m2);
// 交换后,先打印学习,再打印跑!
[Person run];
[Person study];
void method_exchangeImplementations(Method m1 , Method m2)

起始去面试,常常来看面试必要有runtime,特意去大致学习了弹指间,在此记录一下便于将来的复习,恐怕也足以给人家一些经历。

二、在分拣中安装属性,给任何八个对象设置属性

综上说述,分类中是不能设置属性的,假如在分拣的扬言中写@property 只可以为其生成get 和 set 方法的注明,但爱莫能助生成成员变量,便是就算点语法能调用出来,但程序试行后会crash,有人会想到利用全局变量呢?举例那样

int _age;

- (int )age {
    return _age;
}

- (void)setAge:(int)age {
    _age = age;
}

可是全局变量程序整个实施进度中内部存款和储蓄器中独有一份,大家创设四个指标修改其属性值都会修改同三个变量,这样就不可能确认保障像属性同样各类对象都抱有其本人的属性值。这时大家就须求借助runtime为分类扩充属性的效劳了

www.88pt88.com,内需动用的办法 <objc/runtime.h>

set方法,将值value 跟对象object 关联起来(将值value 存款和储蓄到对象object 中)
参数 object:给哪个指标设置属性
参数 key:三个属性对应一个Key,以后得以由此key收取这几个蕴藏的值,key 能够是另外类型:double、int 等,建议用char 能够省去字节
参数 value:给属性设置的值
参数policy:存款和储蓄计谋 (assign 、copy 、 retain正是strong)
void objc_setAssociatedObject(id object , const void *key ,id value ,objc_AssociationPolicy policy)

应用参数key 将对象object中贮存的相应值收取来
id objc_getAssociatedObject(id object , const void *key)

步骤:

1、创立多少个分拣,举个例子给其余八个目的都增多贰个name属性,就是NSObject增添分类(NSObject+Category)
2、先在.h 中@property 注解出get 和 set 方法,方便点语法调用

@property(nonatomic,copy)NSString *name;

3、在.m 中重写set 和 get 方法,内部使用runtime 给属性赋值和取值

char nameKey;

- (void)setName:(NSString *)name {
    // 将某个值跟某个对象关联起来,将某个值存储到某个对象中
    objc_setAssociatedObject(self, &nameKey, name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

- (NSString *)name {
    return objc_getAssociatedObject(self, &nameKey);
}
NSString *_ssex;- (NSString *)Mysex {// return _ssex; return objc_getAssociatedObject(self, &_ssex);}- setMysex:(NSString *)Mysex {// _ssex = Mysex; //将某个值跟某个对象关联起来,将某个值存储到某个对象中 objc_setAssociatedObject(self, &_ssex, Mysex, OBJC_ASSOCIATION_COPY_NONATOMIC);}

一、交流四个办法的兑现,拦截种类自带的措施调用功效

内需选取的不二等秘书技 <objc/runtime.h>

1.到手有些类的类措施

Method class_getClassMethod(Class cls , SEL name)

2.取得有个别类的实例对象方法

Method class_getInstanceMethod(Class cls , SEL name)

3.换到四个点子的落到实处

void method_exchangeImplementations(Method m1 , Method m2)

一、交换五个章程的贯彻,拦截系统自带的艺术调用效率

亟需运用的方法 <objc/runtime.h>
收获某些类的类格局
Method class_getClassMethod(Class cls , SEL name)
获得某些类的实例对象方法
Method class_getInstanceMethod(Class cls , SEL name)
换来五个措施的完毕
void method_exchangeImplementations(Method m1 , Method m2)

void objc_setAssociatedObject(id object , const void *key ,id value ,objc_AssociationPolicy policy)
案例1:获取Person类中有所成员变量的名字和类型

Person.h

@property (nonatomic,copy) NSString *name;

Person.m

- (NSString *)names {
    return _name;
}

- (void)setName:(NSString *)names {
    _name = names;
}

控制器:

 unsigned int outCount = 0;
    Ivar *ivars = class_copyIvarList([Person class], &outCount);

    // 遍历所有成员变量
    for (int i = 0; i < outCount; i++) {
        // 取出i位置对应的成员变量
        Ivar ivar = ivars[i];
        const char *name = ivar_getName(ivar);
        const char *type = ivar_getTypeEncoding(ivar);
        NSLog(@"成员变量类型:%s 成员变量名:%s ",type,name);
    }
    // 注意释放内存!
    free(ivars);

打字与印刷的结果为:

2016-11-04 11:45:11.352 RunTime[2305:175512] 成员变量类型: @"NSString" 成员变量名: _name

别的艺术还在研究中,持续更新。。。

www.88pt88.com 1Paste_Image.png

什么是runtime?

runtime 是 OC底层的一套C语言的API(引入 <objc/runtime.h> 或<objc/message.h>),编译器最终都会将OC代码转化为运行时代码,通过终端命令编译.m 文件:clang -rewrite-objc xxx.m可以看到编译后的xxx.cpp(C++文件)。

地方能够看看,调换了措施的兑现。

案例1:方法简单的沟通

调换类的点子,此处轻易写了把系统的UIView的setBackgroundColor的主意换到了自定义的pb_setBackgroundColor。

 1.首先需要导入系统头文件#import <objc/runtime.h>
 2. 创建一个分类Category,实现方法。(点击右键--New File...--iOS--Objective-C File)。Ps:其中File是文件名,File Type可以选择是否选用分类或者拓展等,Class是选择哪一种 类。

在调节器中首先写三个view,设置背景颜色为革命,发现view的背景象为革命。
制造二个分拣,在.m里福如东海,如下:

#import "UIView+BlackView.h"
#import <objc/runtime.h>

@implementation UIView (BlackView)
+(void)load{

    /** 获取原始setBackgroundColor方法 */
    Method originalM = class_getInstanceMethod([self class], @selector(setBackgroundColor:));

    /** 获取自定义的pb_setBackgroundColor方法 */
    Method exchangeM = class_getInstanceMethod([self class], @selector(zdy_setBackgroundColor:));

    /** 交换方法 */
    method_exchangeImplementations(originalM, exchangeM);
}

/** 自定义的方法 */
-(void)zdy_setBackgroundColor:(UIColor *) color{

    NSLog(@"%s",__FUNCTION__);

    /**
     1.更改颜色
     2.所有继承自UIView的控件,设置背景色都会设置成自定义的'orangeColor'
     3. 此时调用的方法 'pb_setBackgroundColor' 相当于调用系统的 'setBackgroundColor' 方法,原因是在load方法中进行了方法交换.
     4. 注意:此处并没有递归操作.
     */
    [self zdy_setBackgroundColor:[UIColor orangeColor]];
}

接下来在决定在那之中参预头文件,开掘view的水彩已化作樱草黄。

上面举个例证:1.措施轻易易行的沟通创立叁个Person类,类中落到实处以下多个类格局,并在.h 文件中宣示

二、在分拣中设置属性,给其余一个对象设置属性

分类中是无法设置属性的,假设在分拣的宣示中写@property 只好为其生成get 和 set 方法的扬言,但不可能生成成员变量,正是就算点语法能调用出来,但程序实践后会crash,有人会想到利用全局变量呢?

供给利用的不二诀窍 <objc/runtime.h>
1.set艺术,将值value 跟对象object 关联起来(将值value 存款和储蓄到指标object 中)参数 object:给哪个指标设置属性
参数 key:二个属性对应三个Key,今后得以因此key抽取这几个蕴藏的值,key 能够是其他类型:double、int 等,提议用char 可以节约字节
参数 value:给属性设置的值
参数policy:存款和储蓄计谋 (assign 、copy 、 retain正是strong)

void objc_setAssociatedObject(id object , const void *key ,id value ,objc_AssociationPolicy policy)

2.利用参数key 将对象object中贮存的应和值抽出来

id objc_getAssociatedObject(id object , const void *key)

步骤:
1、制造贰个分类,比方给其余叁个指标都丰硕三个name属性,正是NSObject增加分类(NSObject+Category)
2、先在.h 中@property 表明出get 和 set 方法,方便点语法调用

@property(nonatomic,copy)NSString *name;

3、在.m 中重写set 和 get 方法,内部选用runtime 给属性赋值和取值

char nameKey;
- (void)setName:(NSString *)name { 
// 将某个值跟某个对象关联起来,将某个值存储到某个对象中 
objc_setAssociatedObject(self, &nameKey, name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSString *)name { 
return objc_getAssociatedObject(self, &nameKey);
}

在viewdidload中

 unsigned int outCount; Ivar *IvarArray = class_copyIvarList([Person class], &outCount); [person getName:@"feifei"]; [person printfName]; //操作后 object_setIvar(person, IvarArray[1], @"123");// 我在这里是第二个元素 [person printfName];
+load { // 获取两个类的类方法 Method m1 = class_getClassMethod([UIImage class], @selector(imageNamed:)); Method m2 = class_getClassMethod([UIImage class], @selector(junjie_imageNamed:)); // 开始交换方法实现 method_exchangeImplementations;}
Method class_getInstanceMethod(Class cls , SEL name)

导入<objc/runtime.h>得到某些类的类方式:

赢得某些类的实例对象方法

足见大家在外场利用runtime,直接将民用变量的值给修改了,是或不是感觉很吊。。。当然了,有set就有get,object_getIvar方法,他能够取获得上面set设置的值(一般出以往二个类中),风乐趣的童鞋能够去研商切磋。

运作viewdidload,开掘第一个出口男人,第贰个出口女孩子了。方法解惑:

Method class_getClassMethod(Class cls , SEL name)
+ (UIImage *)junjie_imageNamed:(NSString *)name { double version = [[UIDevice currentDevice].systemVersion doubleValue]; if (version >= 7.0) { // 如果系统版本是7.0以上,使用另外一套文件名结尾是‘_os7’的扁平化图片 name = [name stringByAppendingString:@"_os7"]; } return [UIImage junjie_imageNamed:name];}

这五个点子用到了个体变量_name在viewdidload中,作如下操作

因而地点的代码我们能够取得到自定义类中具备成员变量的名字和体系。然而有甚用啊。。。网络有的小编就那样一提,获取到又不能操作有何用。后来意识了那些主意object_setIvar,他能够安装值,接下去本人来教我们怎么用。比方说我们此前在Person类中定义了个体成员变量_name,NSString类型的。在Person类中定义七个章程,如下:

换来五个艺术的落到实处

id objc_getAssociatedObject(id object , const void *key)

runtime简称运营时,约等于在运营时候的片段体制。对于oc函数,属于动态调用进度,在编写翻译的时候并不能够调整真正调用哪些函数,唯有在真正运转的时候才会依据函数的称号找到相应的函数来调用。

set方法,将值value 跟对象object 关联起来(将值value 存款和储蓄到目的object 中)参数 object:给哪些目的设置属性参数 key:壹本性质对应一个Key,未来得以经过key收取这一个蕴藏的值,key 能够是别的类型:double、int 等,以后建议用char 能够节省字节,小编这里不改了参数 value:给属性设置的值参数policy:存款和储蓄计策(assign 、copy 、 retain就是strong)

ivars:重回值,贮存全部得到到的习性。cls:哪个类。outCount:放贰个接收值的地点,用来贮存在属性的个数。

Ivar *ivars = class_copyIvarList(Class cls , unsigned int *outCount)
+ run { NSLog;}+ study { NSLog;}
// 获取两个类的类方法Method m1 = class_getClassMethod([Person class], @selector;Method m2 = class_getClassMethod([Person class], @selector;// 开始交换方法实现method_exchangeImplementations;// 交换后,先打印学习,再打印跑[Person run];[Person study];

在分拣中,是未有质量的,也正是说,你在分拣的.h文件中@property只能成立get和set方法的宣示,但不可能生成属性别变化量,纵然在分拣的.m中大家得以设置个全局变量,代码如下:

 UIImage *image = [UIImage new]; image.Mysex = @"男生"; _MyImage = [UIImage new]; _MyImage.Mysex = @"女生"; NSLog(@"image == %@, _MyImage == %@", image.Mysex, _MyImage.Mysex);

3、分类中重写UIImage的load方法,达成格局的沟通

会意识打字与印刷结果都以女子,那是因为全局变量程序整个施行进程中内部存储器中独有一份,我们制造多少个指标修改其属性值都会修改同一个变量,那样就非常的小概保障像属性同样每一个对象都兼备其和好的属性值。所以那时候就须要借用runtime为分类增加属性的作用了。仍然在刚刚的分类中,代码如下:

使用参数key将对象object中积攒的附和值抽出来。

2.挡住系统方法一般是写个类的归类,然后在分拣中重写该类的一个方法,最终在load方法中调换一下自定义的格局和系统的方法。当然了,自定义方法中最终必必要再调用一下类别的法子。1.为UIImage建一个分类(UIImage+Category)2、在分拣中落到实处三个自定义方法,方法中写要在系统方法中走入的说话,比如版本判别

- getName:(NSString *)junjie { _name = junjie; NSLog(@"他的名字叫:%@",_name);}- printfName { NSLog(@"我的name is %@", _name);}
 unsigned int outCount = 0; Ivar *ivars = class_copyIvarList([Person class], &outCount); NSLog(@"count == %d", outCount); for (int i = 0; i < outCount; i++) { Ivar ivar = ivars[i]; //取出i位置对应的成员变量 const char *name = ivar_getName; const char *type = ivar_getTypeEncoding; NSLog(@"成员变量名:%s, 成员变量类型:%s", name, type); } free; //释放内存
NSString *_ssex;- (NSString *)Mysex { return _ssex;}- setMysex:(NSString *)Mysex { _ssex = Mysex;}

版权声明:本文由大奖888-www.88pt88.com-大奖888官网登录发布于大奖888官网登录,转载请注明出处:www.88pt88.com兴许也能够给别人一些经验,调换四个