NSValue NSNumber NSData类

步骤1 NSValue

我们先看看NSValue能做什么:

一个NSValue对象是用来存储一个C或者Objective-C数据的简单容器。它可以保存任意类型的数据,比如 int,float,char,当然也可以是指pointer, structure, and object id。NSValue类的目标就是允许以上数据类型的数据结构能够被添加到集合里,例如那些需要其元素是对象的数据结构,如NSArray或者NSSet 的实例。需要注意的是NSValue对象一直是不可枚举的。


1、+ (NSValue *)valueWithBytes:(const void *)value objCType:(const char *)type;

创建一个NSValue。

传递的参数是你想要包装的数值的地址(如一个NSSize或你自己的struct),通常得到的是你想要存储的变量的地址(在C语言中使用操作 符&)。你也可以提供一个用来描述这个数据类型的字符串(参数objCType),通常用来说明struct中实体的类型和大小。不需要自己写这 个字符串,@encode编译器指令可以接收数据类型的名称并生成合适的字符串。

2、- (void)getValue:(void *)value(出参);

从NSValue对象中提取数值。

提取的数值,存放在value这个指针所指向的内存块里。

3、Cocoa提供了常用struct数据类型转换成NSValue的便捷方法:

+ (NSValue *)valueWithPoint:(NSPoint)point;

+ (NSValue *)valueWithSize:(NSSize)size;

+ (NSValue *)valueWithRect:(NSRect)rect;

- (NSPoint)pointValue;

- (NSSize)sizeValue;

- (NSRect)rectValue;

NSRect是一个矩形数据种类,NSPoint是起始点,NSSize存储长度和宽度,这些常用的数据种类是C的struct而不是对象。

下边我们通过实验来认识NSValue的使用方式:

#import

int main (int argc, constchar * argv[])

{

@autoreleasepool {

//声明并初始化一个struct NSRectrtc = NSMakeRect(12, 32, 433, 343); //创建一个NSValue: NSValue *value = [NSValue valueWithBytes:&rtc objCType:@encode(NSRect)]; //把value添加到数组中 NSMutableArray *array = [NSMutable ArrayarrayWithCapacity:10]; NSRect rt; [array addObject:value];

 

的 //从数组中取到NSValue,因为只添加了一个,所以小标是0 NSValue *v = [array objectAtIndex:0]; //从value中取得一个NSRect,虽然返回值是void,但其实是它是利用指针返回值

[v getValue:&rt];

//输出结果 NSLog(@"%f %f %f %f", rt.origin.x, rt.origin.y, rt.size.height, rt.size.width); //用快速枚举遍历array并输出NSValue中struct属性的值 for(NSValue *v in array) { NSRect rt; [v getValue:&rt]; NSLog(@"%f %f %f %f", rt.origin.x, rt.origin.y, rt.size.height, rt.size.width); } /便捷的struct转换成NAValue方式 //声明并初始化一个struct NSRect rtc1 = NSMakeRect(100, 200, 300, 400); //创建一个NSValue NSValue *value1 = [NSValue valueWithRect:rtc1]; //把value1添加到数组中 NSMutableArray *array1 = [NSMutable ArrayarrayWithCapacity:10];

[array1 addObject:value1];

NSRect rt1 = [value1 rectValue];

//输出结果

NSLog(@"%f %f %f %f", rt1.origin.x, rt1.origin.y, rt1.size.height, rt1.size.width);

}

} return 0;


注意:在集合中不能存放nil值,因为在NSArray和NSDictionary中nil有特殊的含义。但是在有些时候,确实需要用到这样的空 值,比如在字典中,电话簿中"Zhang San"关键字下有电话号码、家庭住址、Email等等信息,但是现在只知道他的电话号码,这种不知道其他信息


的情况下为了消除一些歧义,有必要将它们设置为空,所以Cocoa提供了NSNull

NSNull只有一个方法:null

[dictionarysetObject:[NSNull null], forKey:"Email"];

if(EmailAdress == [NSNull null])

{

} //to do something


步骤2 NSNumber

NSNumber实际上是NSValue的子类,Cocoa提供了NSNumber类来包装(即以对象形式实现)基本数据类型。

例如以下创建方法:

+ (NSNumber *) numberWithChar: (char) value;

+ (NSNumber *) numberWithInt: (int) value;

+ (NSNumber *) numberWithFloat: (float) value;

+ (NSNumber *) numberWithBool: (BOOL) value;

创建对象后就可以放入字典或数组中。

将基本类型数据封装到NSNumber中后,可以通过下面的实例方法解除装箱,重新获取数据:

- (char) charValue;

- (int) intValue;

- (float) floatValue;

- (BOOL) boolValue;

- (NSString *) stringValue;

术语:将一个基本类型的数据包装成对象叫做装箱(boxing),从对象中提取基本类型的数据叫做取消装箱或拆箱(unboxing)。Objective-C不支持自动装箱。

下面我们通过实验程序掌握NSNumber的基本用法:

#import

int main (int argc, constchar * argv[])

{

 

@autoreleasepool { NSNumber *myNumber,*floatNumber,*intNumber,*number; //创建integer类型对象 intNumber = [NSNumber numberWithInteger:123]; NSLog(@"%i",[intNumber integerValue]); //创建long类型对象 myNumber = [NSNumber numberWithLong:0xababab]; NSLog(@"%lx",[myNumber longValue]); //创建char类型对象 myNumber = [NSNumber numberWithChar:'K']; NSLog(@"%c",[myNumber charValue]); //创建float类型对象 floatNumber = [NSNumber numberWithFloat:123.00]; NSLog(@"%f",[floatNumber floatValue]); //创建double类型对象 myNumber = [NSNumber numberWithDouble:12345e+15]; NSLog(@"%lg",[myNumber doubleValue]); // Wrong access here NSLog(@"%i",[myNumber integerValue]); //判断两个对象的值是否相等 if ([intNumber isEqualToNumber:floatNumber] == YES ) { NSLog(@"值相等"); } else {

NSLog(@"值不相等"); }

//比较两个对象的值大小 if ( [intNumber compare:myNumber] == NSOrderedAscending) { NSLog(@"左边的数字小"); } else { } //初始化实例 NSLog(@"左边的数字大");

number = [[NSNumber alloc] initWithInt:1000];

NSLog(@"%i",[number intValue]);

[number release];

}

return 0;

}


注意:

(1)使用程序行myNumber = [NSNumber numberWithDouble: 12345e+15]; 创建double对象,然后尝试(不正确地)使用如下程序行来检索并显示它的值:

NSLog (@”%i”, [myNumber integerValue]);

将得到以下输出:

并且,系统也没有给出出错消息。一般来说,由程序员负责确保正确地进行检索,如果在NSNumber对象中存储了一个值,那么也要用一致的方式进行检索。

(2) NSNumber继承自NSObject,可以使用比较 compare:isEqualToNumber等消息。

(3)此外,还可以使用实例方法初始化NSNumber对象,这些都是以initWith开头,比如initWithInt。

number = [[NSNumber alloc] initWithInt:1000];

注意不能重新初始化前面创建的NSNumber对象的值。例如,不能使用下面的语句设置存储在NSNumber对象myNumber中的整数: [myNumber initWithInt: 1000];

当程序执行时,该条语句将产生一条错误。


步骤3 NSData

Cocoa中使用NSData类型来实现缓冲区,其实你可以把NSData当作JAVA 中的字节数组,用于存储二进制的数据类型,譬如:从网络下载回来的文件等。对于32位应用程序,NSData缓存区最多可以存储2GB的数据。


NSData的创建使用如下的类方法:

+(NSData*)dataWithBytes:(const void*) bytes length:(NSUInteger) length;

第一参数指定你要缓冲的数据的起始位置,也就是指针里存储的首地址,第二个参数指定数据的长度。例如:

#import

int main (int argc, constchar * argv[])

{

@autoreleasepool {

constchar *string="Hi,this is a c string";

//创建NSData对象 NSData *data=[NSData dataWithBytes:string length:strlen(string)+1]; NSLog(@"------%@",data); NSLog(@"length=%d,string='%s'",[data length],[data bytes]); //将数据写入文件中

[data writeToFile:@"/Users/zhangkoumine/Desktop/myfile.txt"

atomically:TRUE];

}

return 0;

}

首先我们定义了一个C语言的字符序列,然后把它的指针、长度赋给了NSData的创建方法。这里需要注意的是由于C语言的字符序列的指针地址本身就 是数组的首地址,所以不需要再加&计算指针的地址了。另外,长度要再加1也是C语言的特性。C语言里的字符串以\0结尾。你会看到Shell窗口 输出一组16进制的数字,也就是缓冲区中存储的内容。NSData是长度不可变的数据缓冲区,还有一个NSMutableData用来存储长度可变的数据 缓冲区。 通常我们在进行文件的读写操作时会用到NSData类,将文件内容读入缓冲区或者将缓冲区的内容写入到一个文件。下面代码展示了如何将文件的内容读入内存 缓冲区,然后再将缓冲区的内容写入到另一个文件中。



例如读取testfile.txt文件中的数据,并将数据写到newfile.txt文件中。


#import

int main (int argc, constchar * argv[])

{

@autoreleasepool { NSFileManager * fm; NSData *fileData; fm = [NSFileManager defaultManager]; //读取文件testfile.txt 使用绝对路径 fileData = [fm contentsAtPath:@"/Users/zhangkoumine/Desktop/testfile.txt"]; if(fileData == nil) { NSLog(@"File read failed!"); return 1;

}

//将数据写到 newfile.txt (相当于拷贝文件)

if([fm createFileAtPath:@"/Users/zhangkoumine/Desktop/newfile.txt"

contents:fileData attributes:nil] == NO)

{

NSLog(@"Couldn't create the copy!");

return 2;

}

NSLog(@"File copy was successful!"); //读取拷贝后的文件 newfile.txt中的数据NSLog(@"%@",

[NSString stringWithContentsOfFile:@"/Users/zhangkoumine/Desktop/newfile.txt" encoding:NSUTF8StringEncoding error:nil]);

}

return 0;

}


在实际开发过程中,经常需要将NSData类型与其他类型进行转换。

1, NSData 与 NSString

//NSData --> NSString

NSString *aString = [[NSString alloc] initWithData:adata encoding:NSUTF8StringEncoding]; //NSString --> NSData

NSString *aString = @"1234";

NSData *aData = [aString dataUsingEncoding: NSUTF8StringEncoding];

2, NSData 与 Byte

//NSData --> Byte

NSString *testString = @"1234567890";

NSData *testData = [testString dataUsingEncoding: NSUTF8StringEncoding];

Byte *testByte = (Byte *)[testData bytes];

//Byte --> NSData

Byte byte[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23};

NSData *adata = [[NSData alloc] initWithBytes:byte length:24];

3, NSData 与 UIImage

//NSData --> UIImage

UIImage *aimage = [UIImage imageWithData: imageData];

//从本地文件沙盒中取图片并转换为NSData

NSString *path = [[NSBundle mainBundle] bundlePath];

NSString *name = [NSString stringWithFormat:@"ceshi.png"];

NSString *finalPath = [path stringByAppendingPathComponent:name];

NSData *imageData = [NSData dataWithContentsOfFile: finalPath];

UIImage *aimage = [UIImage imageWithData: imageData];

UIImage-> NSData

NSData *imageData = UIImagePNGRepresentation(aimae);

4, NSData 与 NSMutableData

//NSData --> MSMutableData

NSData *data=[[NSData alloc]init];

NSMutableData *mdata=[[NSMutableData alloc]init];


mdata=[NSData dataWithData:data];

5,NSData合并为一个NSMutableData

- (NSString *)filePathWithName:(NSString *)filename

{

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

NSString *documentsDirectory = [paths objectAtIndex:0];

return [documentsDirectory stringByAppendingPathComponent:filename];

}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

//音频文件路径

NSString *mp3Path1 = [[NSBundle mainBundle] pathForResource:@"1" ofType:@"mp3"]; NSString *mp3Path2 = [[NSBundle mainBundle] pathForResource:@"2" ofType:@"mp3"]; //音频数据

NSData *sound1Data = [[NSData alloc] initWithContentsOfFile: mp3Path1];

NSData *sound2Data = [[NSData alloc] initWithContentsOfFile: mp3Path2];

//合并音频

NSMutableData *sounds = [NSMutableData alloc];

[sounds appendData:sound1Data];

[sounds appendData:sound2Data];

//保存音频

NSLog(@"data length:%d", [sounds length]);

[sounds writeToFile:[self filePathWithName:@"tmp.mp3"] atomically:YES];

[window makeKeyAndVisible];

return YES;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值