class_copyIvarList方法取得实例变量问题抓住的盘算。class_copyIvarList方法获得实例变量问题掀起的琢磨。

by admin on 2018年10月19日

以runtime.h中,你可以由此中间的class_copyIvarList方法来收获实例变量。具体的落实如下(记得导入头文件<objc/runtime.h>):

每当runtime.h中,你可由此内部的class_copyIvarList方法来得到实例变量。具体的实现如下(记得导入头文件<objc/runtime.h>):

- (NSArray *)ivarArray:(Class)cls {
    unsigned int stuIvarCount = 0;
    Ivar *ivars = class_copyIvarList(cls, &stuIvarCount);
    if (stuIvarCount == 0) {
        return nil;
    }
    NSMutableArray *arr = [[NSMutableArray alloc] initWithCapacity:stuIvarCount];
    for (int i = 0;i<stuIvarCount;i++) {
        Ivar ivar = ivars[i];
        NSString *ivarName = [NSString stringWithUTF8String:ivar_getName(ivar)];
        NSLog(@"%@",ivarName);
        [arr addObject:ivarName];
    }
    free(ivars);
    return arr;
}
- (NSArray *)ivarArray:(Class)cls {
    unsigned int stuIvarCount = 0;
    Ivar *ivars = class_copyIvarList(cls, &stuIvarCount);
    if (stuIvarCount == 0) {
        return nil;
    }
    NSMutableArray *arr = [[NSMutableArray alloc] initWithCapacity:stuIvarCount];
    for (int i = 0;i<stuIvarCount;i++) {
        Ivar ivar = ivars[i];
        NSString *ivarName = [NSString stringWithUTF8String:ivar_getName(ivar)];
        NSLog(@"%@",ivarName);
        [arr addObject:ivarName];
    }
    free(ivars);
    return arr;
}

万一上面代码。其中cls就是你如果得到实例变量的近乎,stuIvarCount用来承载要博得类的实例变量的个数。打印出来的ivarName就是cls的实例变量。接下来对这办法开展辨析:
第一看一下里面的Ivar,先押一下定义:

若果上面代码。其中cls就是公如拿走实例变量的切近,stuIvarCount用来承载要取得类的实例变量的个数。打印出的ivarName就是cls的实例变量。接下来对这点子开展分析:
首先看一下里面的Ivar,先押一下定义:

/// An opaque type that represents an instance variable.
typedef struct objc_ivar *Ivar;

struct objc_ivar {
    char * _Nullable ivar_name                               OBJC2_UNAVAILABLE;  //变量名字
    char * _Nullable ivar_type                               OBJC2_UNAVAILABLE;   //变量类型
    int ivar_offset                                          OBJC2_UNAVAILABLE; //偏移量
#ifdef __LP64__
    int space                                                OBJC2_UNAVAILABLE;  //存储空间
#endif
}    
/// An opaque type that represents an instance variable.
typedef struct objc_ivar *Ivar;

struct objc_ivar {
    char * _Nullable ivar_name                               OBJC2_UNAVAILABLE;  //变量名字
    char * _Nullable ivar_type                               OBJC2_UNAVAILABLE;   //变量类型
    int ivar_offset                                          OBJC2_UNAVAILABLE; //偏移量
#ifdef __LP64__
    int space                                                OBJC2_UNAVAILABLE;  //存储空间
#endif
}    

Ivar是一个称作objc_ivar的结构体指针,其中的
ifdef判断是判断时装备是否是64各设备,这里可以拉开出一个方式:

Ivar是一个名为objc_ivar的结构体指针,其中的
ifdef判断是判断时设施是否是64各类设备,这里可以延长出一个法:

//判断当前设备是否是64位设备,也可以用这个方法判断是否是32位设备
- (BOOL)is64Bit {
#if defined(__LP64__) && __LP64__
    return YES;
#else
    return NO;
#endif
}

OBJC_EXPORT Ivar _Nonnull * _Nullable
class_copyIvarList(Class _Nullable cls, unsigned int * _Nullable outCount) 
    OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
//判断当前设备是否是64位设备,也可以用这个方法判断是否是32位设备
- (BOOL)is64Bit {
#if defined(__LP64__) && __LP64__
    return YES;
#else
    return NO;
#endif
}

OBJC_EXPORT Ivar _Nonnull * _Nullable
class_copyIvarList(Class _Nullable cls, unsigned int * _Nullable outCount) 
    OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);

class_copyIvarList的诠释如下:
图片 1
它回到的是一个Ivar的勤组,这个数组里面含有了卿若查看类的兼具实例变量,但是未包由父类继承过来的。如果您传入的近乎没有实例变量或者改class为Nil,那么该方式返回的饶是NULL,count值也不怕变成了0。有一些要注意:而得动free()方法以该数组自由
接下来就经过for循环遍历,通过ivar _ getName拿到ivarName。
上述就是是本着clas_copyIvarList的介绍。
它还有一个不过常用的采取办法(在支付中常采取的):根据字典或者json字符串转化为model,在网络要返回数据经常经常用到。使用办法就是是祥和写一个基类的model,然后被项目受到之所以到的model都延续自此基类,基类中之最主要代码如下:

class_copyIvarList的注释如下:
图片 2
它们回到的凡一个Ivar的一再组,这个数组里面含了您而查看类的装有实例变量,但是未包于父类继承过来的。如果你传入的类没有实例变量或者改class为Nil,那么该办法返回的就是是NULL,count值也尽管改成了0。有某些消专注:而不能不用free()方法将该数组自由
接下来就经过for循环遍历,通过ivar _ getName拿到ivarName。
上述就是指向clas_copyIvarList的介绍。
其还有一个极其常用之动方法(在开发被时下的):根据字典或者json字符串转化为model,在网络要返回数据经常经常用到。使用办法就是友善写一个基类的model,然后让种蒙因故到之model都累自此基类,基类中的首要代码如下:

+ (instancetype)zg_modelFromDic:(NSDictionary *)dataDic {
    id model = [[self alloc] init];  
    unsigned int count = 0;

    Ivar *ivarsA = class_copyIvarList(self, &count);
    if (count == 0) {
        return model;
    }
    for (int i = 0;i < count; i++) {
        Ivar iv = ivarsA[i];
        NSString *ivarName = [NSString stringWithUTF8String:ivar_getName(iv)];
        ivarName = [ivarName substringFromIndex:1];
        id value = dataDic[ivarName];
        [model setValue:value forKey:ivarName];
    }
    free(ivarsA);
    return model;
}
+ (instancetype)zg_modelFromDic:(NSDictionary *)dataDic {
    id model = [[self alloc] init];  
    unsigned int count = 0;

    Ivar *ivarsA = class_copyIvarList(self, &count);
    if (count == 0) {
        return model;
    }
    for (int i = 0;i < count; i++) {
        Ivar iv = ivarsA[i];
        NSString *ivarName = [NSString stringWithUTF8String:ivar_getName(iv)];
        ivarName = [ivarName substringFromIndex:1];
        id value = dataDic[ivarName];
        [model setValue:value forKey:ivarName];
    }
    free(ivarsA);
    return model;
}

此是把字典转成为model,先用class_copyIvar获得该model的持有实例变量,然后通过kvc对性能进行赋值。最终回model。这里出个点要留意以下几点:

这里是管字典转成model,先用class_copyIvar获得该model的拥有实例变量,然后经过kvc对性能进行赋值。最终回到model。这里出个点需要注意以下几点:

  1. 卿的model的性能名称要和服务端返回的多少一致,比如您的model有只特性叫做name,那么你服务端返回的数据字典里的相应属性为要是叫name,因为这个点子是依据性从字典里用多少的。你为堪开一个投,让于定义之实例变量名称映射到服务端提供的变量名称。
  2. 兑现中有只substringFromIndex:操作,其目的就是拿以该措施以到之实例变量前面的”
    _ “去掉。所以您不过好应用 @property
    进行性能声明,并且不要错过窜自动生成的实例变量。(@property =
    getter + setter + _ ivar,这里的 _
    ivar其实就是编译器帮咱别的实例变量)
  1. 而的model的属性名称要跟服务端返回的数额一致,比如你的model有个属性叫做name,那么你服务端返回的多寡字典里的相应属性也使叫name,因为这个方式是冲性从字典里将多少的。你为堪开一个射,让于定义之实例变量名称映射到服务端提供的变量名称。
  2. 实现中有只substringFromIndex:操作,其目的就是拿用该法以到的实例变量前面的”
    _ “去掉。所以您顶好应用 @property
    进行性能声明,并且不要错过修改自动生成的实例变量。(@property =
    getter + setter + _ ivar,这里的 _
    ivar其实就是编译器帮我们别的实例变量)

通下去你可以品尝去得UILabel的实例变量列表:

搭下去你可以尝尝去抱UILabel的实例变量列表:

[self ivarArray:[UILabel class]]
[self ivarArray:[UILabel class]]

您晤面意识将到之结果是如此的:

汝见面发现用到之结果是这样的:

(
    "_size",
    "_highlightedColor",
    "_numberOfLines",
    "_measuredNumberOfLines",
    "_baselineReferenceBounds",
    "_lastLineBaseline",
    "_previousBaselineOffsetFromBottom",
    "_firstLineBaseline",
    "_previousFirstLineBaseline",
    "_minimumScaleFactor",
    "_content",
    "_synthesizedAttributedText",
    "_defaultAttributes",
    "_fallbackColorsForUserInterfaceStyle",
    "_minimumFontSize",
    "_lineSpacing",
    "_layout",
    "_scaledMetrics",
    "_cachedIntrinsicContentSize",
    "_contentsFormat",
    "_cuiCatalog",
    "_cuiStyleEffectConfiguration",
    "_textLabelFlags",
    "_adjustsFontForContentSizeCategory",
    "__textColorFollowsTintColor",
    "_preferredMaxLayoutWidth",
    "_multilineContextWidth",
    "__visualStyle"
)
(
    "_size",
    "_highlightedColor",
    "_numberOfLines",
    "_measuredNumberOfLines",
    "_baselineReferenceBounds",
    "_lastLineBaseline",
    "_previousBaselineOffsetFromBottom",
    "_firstLineBaseline",
    "_previousFirstLineBaseline",
    "_minimumScaleFactor",
    "_content",
    "_synthesizedAttributedText",
    "_defaultAttributes",
    "_fallbackColorsForUserInterfaceStyle",
    "_minimumFontSize",
    "_lineSpacing",
    "_layout",
    "_scaledMetrics",
    "_cachedIntrinsicContentSize",
    "_contentsFormat",
    "_cuiCatalog",
    "_cuiStyleEffectConfiguration",
    "_textLabelFlags",
    "_adjustsFontForContentSizeCategory",
    "__textColorFollowsTintColor",
    "_preferredMaxLayoutWidth",
    "_multilineContextWidth",
    "__visualStyle"
)

但是超过反到UILabel.h,你会意识其中来成千上万的性质不带有在我们根据拖欠措施得出的习性数组里面,而且以该方式获得的属性在UILabel.h里面连没。这个是啊由呢?
预先看一下好多UILabel里面的习性没有以数组里面打印问题:猜想应该是在UILabel.m里面用了
@dynamic。导致没有自动生成getter、setter和ivar,所以无当数组里面富含。

然而越反至UILabel.h,你会意识中间有很多的属性不带有在我们根据该措施得出的性数组里面,而且以该方式获得的性质在UILabel.h里面连没有。这个是啊由呢?
先行看一下好多UILabel里面的性能没有以数组里面打印问题:猜想应该是在UILabel.m里面用了
@dynamic。导致没有自动生成getter、setter和ivar,所以无当数组里面含有。

@synthsize:如果没手动实现setter/getter方法那么会自动生成,自动生成_var变量。如果非写,默认生成getter/setter和_var。你呢得以用该要字自己安装自动变量的称谓。
@dynamic告诉编译器:属性的setter/getter需要用户自己实现,不自动生成,而且也未见面起_var变量。

@synthsize:如果没有手动实现setter/getter方法那么会自动生成,自动生成_var变量。如果无写,默认生成getter/setter和_var。你为堪运用该要字自己设置自动变量的称。
@dynamic告诉编译器:属性之setter/getter需要用户自己实现,不自动生成,而且为非会见生出_var变量。

也就是说在UILabel里面虽然来只text的性,也许在UILabel.m里面都包含:

也就是说在UILabel里面虽然发出个text的特性,也许在UILabel.m里面已包含:

@dynamic text;
@dynamic text;

这样的话在实现中没起实例变量,只是手动实现了getter和setter,所以便无见面显得text属性在方得到的数组里面了。
关于数组中生UILabel.h里面没的变量,这个就好掌握了,有或在UILabel.m里面上加了一些实例变量或者以运作时加加了这些实例变量。

这样的话在贯彻中没有来实例变量,只是手动实现了getter和setter,所以就未会见显text属性在方得到的数组里面了。
有关数组中来UILabel.h里面没底变量,这个就好掌握了,有或在UILabel.m里面加加了片实例变量或者以运作时加加了这些实例变量。

除了这措施外,你还可行使class_copyPropertyList方法,这个是以到的具有用
@property
声明的属性,包括于.m里面长的性能(所以打印出来的也许只要于真实在.h里面来看的多),具体贯彻同地方的得到方式类似:

除开之道之外,你还可采用class_copyPropertyList方法,这个是将到之拥有用
@property
声明的特性,包括以.m里面添加的属性(所以打印出的可能使较真正在.h里面看到底差不多),具体实现和方的取得方式类似:

- (NSArray *)propertyArr:(Class)cls {
    unsigned count = 0;
    objc_property_t *properties = class_copyPropertyList(cls, &count);
    if (count == 0) {
        return nil;
    }
    NSMutableArray *arr = [[NSMutableArray alloc] initWithCapacity:count];
    for (int i = 0; i < count; i ++) {
        objc_property_t property = properties[i];
        NSString *propertyName = [NSString stringWithUTF8String:property_getName(property)] ;
        [arr addObject:propertyName];
    }
    free(properties);
    return arr;
}
- (NSArray *)propertyArr:(Class)cls {
    unsigned count = 0;
    objc_property_t *properties = class_copyPropertyList(cls, &count);
    if (count == 0) {
        return nil;
    }
    NSMutableArray *arr = [[NSMutableArray alloc] initWithCapacity:count];
    for (int i = 0; i < count; i ++) {
        objc_property_t property = properties[i];
        NSString *propertyName = [NSString stringWithUTF8String:property_getName(property)] ;
        [arr addObject:propertyName];
    }
    free(properties);
    return arr;
}

个中的copyPropertyList方法解释如下:
图片 3
记得使用过后为要调用free去放活数组。(PS:在源代码中暂时未找到objc_property结构体的征)因此,你可经动该法来贯彻字典或者json字符串转model操作:

个中的copyPropertyList方法解释如下:
图片 4
记使用了后为如调用free去放活数组。(PS:在源代码中暂时勿找到objc_property结构体的征)因此,你可以经过动用该办法来贯彻字典或者json字符串转model操作:

+ (instancetype)zg_modelFromDic:(NSDictionary *)dataDic {
    id model = [[self alloc] init];
    unsigned int count = 0;

    objc_property_t *properties = class_copyPropertyList([self class], &count);
    if (count == 0) {
        return model;
    }
    for (int i = 0;i < count; i++) {
        objc_property_t property = properties[i];
        NSString *propertyName = [NSString stringWithUTF8String:property_getName(property)];
        id value = dataDic[propertyName];
        [model setValue:value forKey:propertyName];
    }
    free(properties);
    return model;
}
+ (instancetype)zg_modelFromDic:(NSDictionary *)dataDic {
    id model = [[self alloc] init];
    unsigned int count = 0;

    objc_property_t *properties = class_copyPropertyList([self class], &count);
    if (count == 0) {
        return model;
    }
    for (int i = 0;i < count; i++) {
        objc_property_t property = properties[i];
        NSString *propertyName = [NSString stringWithUTF8String:property_getName(property)];
        id value = dataDic[propertyName];
        [model setValue:value forKey:propertyName];
    }
    free(properties);
    return model;
}

少栽方法都只是实现model转换操作。
如上就是是由class_copyIvarList所引发的构思。

点滴种植方法都只是实现model转换操作。
如上就是出于class_copyIvarList所引发的思考。

转载请标明来源:http://www.cnblogs.com/zhanggui/p/8177400.html

转载请标明源于:http://www.cnblogs.com/zhanggui/p/8177400.html

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图