欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

ios学习路线—Objective-C(装箱和拆箱)

程序员文章站 2022-03-24 12:29:06
概述 从前面的博文我们也可以看到,数组和字典中只能存储对象类型,其他基本类型和结构体是没有办法放到数组和字典中的,当然你也是无法给它们发送消息的也就是说有些NSObject的方法是无法调用的,这个时候通常会用到装箱boxing和拆箱unboxing。 其实各种高级语言基本上都有装箱和拆 箱的过程,例 ......

概述 
从前面的博文我们也可以看到,数组和字典中只能存储对象类型,其他基本类型和结构体是没有办法放到数组和字典中的,当然你也是无法给它们发送消息的也就是说有些nsobject的方法是无法调用的,这个时候通常会用到装箱boxing和拆箱unboxing。

其实各种高级语言基本上都有装箱和拆 箱的过程,例如c#中我们将基本数据类型转化为object就是一个装箱的过程,将这个object对象转换为基 本数据类型的过程就是拆箱,而且在c#中装箱的过程可以自动完成,基本数据类型可以直接赋值给object 对象。但是在objc中装箱的过程必须手动实现,objc不支持自动装箱。

对象的装箱和拆箱,在objc中我们一般将基本数据类型装箱成 nsnumber 类型当然它也是 nsobject 的子类,但是 nsnumber 不能对结构体装箱,调用其对应的方法进行转换:

+(nsnumber *)numberwithchar:(char)value; 
+(nsnumber *)numberwithint:(int)value;
+(nsnumber *)numberwithfloat:(float)value; 
+(nsnumber *)numberwithdouble:(double)value; 
+(nsnumber *)numberwithbool:(bool)value; 
+(nsnumber *)numberwithinteger:(nsinteger)value;

拆箱的过程就更加简单了,可以调用如下方法:

-(char)charvalue;
-(int)intvalue;
-(float)floatvalue; 
-(double)doublevalue;
-(bool)boolvalue;

示例

#import <foundation/foundation.h>

/*可以存放基本类型到数组、字典*/
void test1() {
    //包装类nsnumber,可以包装基本类型但是无法包装结构体类型
    nsnumber *number1 = [nsnumber numberwithchar:'a'];//'a'是一个c语言的char类型我们无 法放倒nsarray中,但是我们可以通过nsnumber包装
    nsarray *array1 = [nsarray arraywithobject:number1];
    nslog(@"%@", array1);
    /*结果:
    (
    97
    ) */
    nsnumber *number2 = [array1 lastobject];
    nslog(@"%@", number2);//返回的不是基本类型,结果:97
    char char1 = [number2 charvalue];//number转化为char
    nslog(@"%c", char1); //结果:a
}

int main(int argc, const char *argv[]) {
    @autoreleasepool {
        test1();
    }
    return 0;
}

 

结构体的装箱和拆箱 
上面我们看到了基本数据类型的装箱和拆箱过程,那么结构体呢? 
这个时候我们需要引入另外一个类型nsvalue,其实上面的nsnumber就是nsvalue的子类,它包装了一些基本数据类型的常用装箱、拆箱方法,当要对结构体进行装箱、拆箱操作我们需要使用nsvalue,nsvalue可以对任何数据类型进行装箱、拆箱操作。

事实上对于常用的结构体foundation已经为我们提供好了具体的装箱方法:

+(nsvalue *)valuewithpoint:(nspoint)point;
+(nsvalue *)valuewithsize:(nssize)size;
+(nsvalue *)valuewithrect:(nsrect)rect;

对应的拆箱方法:

-(nspoint)pointvalue; 
-(nssize)sizevalue; 
-(nsrect)rectvalue;

示例

#import <foundation/foundation.h>

//nsnumber是nsvalue的子类,而nsvalue可以包装任何类型,包括结构体
void test1() {
    cgpoint point1 = cgpointmake(10, 20);
    nsvalue *value1 = [nsvalue valuewithpoint:point1];//对于系统自带类型一般都有直接的方 法进行包装
    nsarray *array1 = [nsarray arraywithobject:value1];//放倒数组中
    nslog(@"%@",array1);
    /*结果:
    (
    "nspoint: {10, 20}"
    ) */
    nsvalue *value2 = [array1 lastobject];
    cgpoint point2 = [value2 pointvalue];//同样对于系统自带的结构体有对应的取值方法(例如 本例pointvalue)
    nslog(@"x=%f,y=%f", point2.x, point2.y);//结果:x=10.000000,y=20.000000
}

int main(int argc, const char *argv[]) {
    @autoreleasepool {
        test1();
    }
    return 0;
}

 

自定义的结构体类型的装箱和拆箱  如果是我们自定义的结构体类型呢,这个时候我们需要使用nsvalue如下方法进行装箱:

+(nsvalue *)valuewithbytes:(const void *)value objctype:(const char *)type;

调用下面的方法进行拆箱:

-(void)getvalue:(void *)value;

示例

#import <foundation/foundation.h>

typedef struct {
    int year;
    int month;
    int day;
} date;

//nsnumber是nsvalue的子类,而nsvalue可以包装任何类型,包括结构体
void test1() {
    //如果我们自己定义的结构体包装
    date date = {2014, 2, 28};
    char *type = @encode(date);
    nsvalue *value3 = [nsvalue value:&date withobjctype:type];//第一参数传递结构体地址,第二个参数传递类型字符串
    nsarray *array2 = [nsarray arraywithobject:value3];
    nslog(@"%@", array2);
    /*结果:
    (
    "<de070000 02000000 1c000000>"
    ) */
    date date2;
    [value3 getvalue:&date2];//取出对应的结构体,注意没有返回值
    //[value3 objctype]//取出包装内容的类型 nslog(@"%i,%i,%i",date2.year,date2.month,date2.day); //结果:2014,2,28
}

int main(int argc, const char *argv[]) {
    @autoreleasepool {
        test1();
    }
    return 0;
}