OC-类型编码(TypeEncodings)

类型编码

为了帮助运行时系统,编译器将每个方法的返回值和参数编码成一个C字符串,并将这个字符串和OC的方法选择器进行关联。我们可以用编译器指令@encode来获取这个C字符串。当你给一个指定的类型(这个类型可以是基本数据类型,如int,可以是一个指针,一个结构体,类名等,也就是可以作为sizeof()参数的任何类型),@encode会返回一个将这个类型编码后的C字符串。总结为一句话:用一个C字符串来表示一个数据类型
举例:

int main(int argc, const char * argv[]) {
  @autoreleasepool {
    char *buf1 = @encode(int);
    char *buf2 = @encode(float);
    char *buf3 = @encode(NSString *);
    NSLog(@"%s",buf1);
    NSLog(@"%s",buf2);
    NSLog(@"%s",buf3);
  }
  return 0;
}

输出结果如下:

i
f
@

下面这个列表列出了一些类型码及其代表的意义

Code Meaning
c A char
i An int
s A short
l A long
l is treated as a 32-bit quantity on 64-bit programs.
q A long long
C An unsigned char
I An unsigned int
S An unsigned short
L An unsigned long
Q An unsigned long long
f A float
d A double
B A C++ bool or a C99 _Bool
v A void
* A character string (char *)
@ An object (whether statically typed or typed id)
# A class object (Class)
: A method selector (SEL)
[array type] An array
{name=type...} A structure
(name=type...) A union
bnum A bit field of num bits
^type A pointer to type
? An unknown type (among other things, this code is used for function pointers)

注意:

  • OC 不支持 long double类型,@encode(long double)将会返回 d ,和double类型的编码一致。
  • c 数组,在经过编码后,会在类型前加上数组的个数,如存储12个float类型的指针数组,将会返回 [12^f]
  • 类对象会被当作结构体来处理,如@encode(NSObject)将会返回{NSObject=#}

我们可以将列表中的这些值打印出来

int main(int argc, const char * argv[]) {
  @autoreleasepool {
    NSLog(@"char --> %s",@encode(char));
    NSLog(@"int --> %s",@encode(int));
    NSLog(@"short --> %s",@encode(short));
    NSLog(@"long --> %s",@encode(long));
    NSLog(@"long long --> %s",@encode(long long));
    NSLog(@"unsigned char --> %s",@encode(unsigned char));
    NSLog(@"unsigned int --> %s",@encode(unsigned int));
    NSLog(@"unsigned short --> %s",@encode(unsigned short));
    NSLog(@"unsigned long --> %s",@encode(unsigned long long));
    NSLog(@"float --> %s",@encode(float));
    NSLog(@"bool --> %s",@encode(bool));
    NSLog(@"void --> %s",@encode(void));
    NSLog(@"char * --> %s",@encode(char *));
    NSLog(@"id --> %s",@encode(id));
    NSLog(@"Class --> %s",@encode(Class));
    NSLog(@"SEL --> %s",@encode(SEL));
    int array[] = {1,2,3};
    NSLog(@"int[] --> %s",@encode(typeof(array)));
    typedef struct person{
        char *name;
        int age;
    }Person;
    NSLog(@"struct --> %s",@encode(Person));
    
    typedef union union_type{
        char *name;
        int a;
    }Union;
    NSLog(@"union --> %s",@encode(Union));

    int a = 2;
    int *b = {&a};
    NSLog(@"int[] --> %s",@encode(typeof(b)));

}
  return 0;
}

打印结果和列表中所列相同,这里不再列出。

应用示例

区分一个数组中NSNumber值的具体数据类型。

int main(int argc, const char * argv[]) {
  @autoreleasepool {
    NSNumber *num1 = [NSNumber numberWithInt:1];
    NSNumber *num2 = [NSNumber numberWithFloat:1.5];
    NSNumber *num3 = [NSNumber numberWithDouble:1.6];
    NSNumber *num4 = [NSNumber numberWithChar:'A'];
    NSArray *arr = @[num1,num2,num3,num4];
    for (int i=0; i<arr.count; i++) {
        NSNumber *num = arr[i];
        if(0 == strcmp([num objCType], @encode(int))){
            NSLog(@"num%d是int型数据",i);
        }else if(0 == strcmp([num objCType], @encode(float))){
            NSLog(@"num%d是float型数据",i);
        }else if(0 == strcmp([num objCType], @encode(double))){
            NSLog(@"num%d是double型数据",i);
        }else if(0 == strcmp([num objCType], @encode(char))){
            NSLog(@"num%d是char型数据",i);
        }else{
            NSLog(@"num%d是其它类型数据",i);
        }
    }
  }
  return 0;
}

方法的类型编码

runtime系统预备了一些编码,这些编码在协议中声明方法时会用到。编码列表如下:

Code Meaning
r const
n in
N inout
o out
O bycopy
R byref
V oneway

属性的类型编码

当我们声明属性时,编译器会产生一些与封装的类,类别或协议相关联的一些元数据,我们可以获得这些元数据类型作为一个@encode编译后的C字符串。总结为一句话:就是用一个C字符串来表示属性的一些描述信息
我们可以通过property_getAttributes函数去获得属性的一个属性或者属性的其他属性经过@encode编码之后的C字符串。这个字符串以T开头,后面紧跟@encode编码后的C字符串,然后用‘,’分隔,最后以V紧跟实例变量的返回值结束。在T和V之间,属性的属性用下列字符来描述:

Code Meaning
R The property is read-only (readonly).
C The property is a copy of the value last assigned (copy).
& The property is a reference to the value last assigned (retain).
N The property is non-atomic (nonatomic).
G<name> The property defines a custom getter selector name. The name follows the G (for example, GcustomGetter,).
S<name> The property defines a custom setter selector name. The name follows the S (for example, ScustomSetter:,).
D The property is dynamic (@dynamic).
W The property is a weak reference (__weak).
P The property is eligible for garbage collection.
t<encoding> Specifies the type using old-style encoding.
代码示例

Person.h

@interface Person : NSObject
@property (nonatomic,copy) NSString *name;
@end

main.m

#import <Foundation/Foundation.h>
#import "Person.h"
#import <objc/runtime.h>

int main(int argc, const char * argv[]) {
  @autoreleasepool {
    Person *p = [[Person alloc] init];
    unsigned int outCount = 0;
    objc_property_t *props = class_copyPropertyList([p class], &outCount);
    for (int i=0 ; i<outCount; i++) {
        objc_property_t prop = props[i];
        NSLog(@"%s",property_getAttributes(prop));
    }
  }
  return 0;
}

输出结果:

T@"NSString",C,N,V_name

输出结果解释:

T@"NSString":表示这个属性的类型是 NSString 型
C:表示属性的引用类型是 copy
N:表示 nonatomic
V_name: 表示属性生成的实例变量是:_name,我们可以用_name来访问属性name的值。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,802评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,109评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,683评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,458评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,452评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,505评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,901评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,550评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,763评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,556评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,629评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,330评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,898评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,897评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,140评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,807评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,339评论 2 342

推荐阅读更多精彩内容