数组和字典中只能存储对象类型,其他基本类型和结构体是没有办法放到数组和字典中的,当然你也是无法给它们发送消息的(也就是说有些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; 
 
简单看一个例子 
 
// 
//  main.m 
//  FoundationFramework 
// 
//  Created by Kenshin Cui on 14-2-16. 
//  Copyright (c) 2014年 Kenshin Cui. All rights reserved. 
// 
 
#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[]) { 
    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; 
 
// 
//  main.m 
//  FoundationFramework 
// 
//  Created by Kenshin Cui on 14-2-16. 
//  Copyright (c) 2014年 Kenshin Cui. All rights reserved. 
// 
 
#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[]) { 
    test1(); 
    return  0; 
} 
  
 
那么如果是我们自定义的结构体类型呢,这个时候我们需要使用NSValue如下方法进行装箱: 
 
+(NSValue *)valueWithBytes:(const void *)value objCType:(const char *)type; 
 
调用下面的方法进行拆箱: 
 
-(void)getValue:(void *)value; 
 
// 
//  main.m 
//  FoundationFramework 
// 
//  Created by Kenshin Cui on 14-2-16. 
//  Copyright (c) 2014年 Kenshin Cui. All rights reserved. 
// 
 
#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[]) { 
    test1(); 
    return  0; 
} |   
        
 
    
    
    
     
 
 |