您的位置:首页 > 产品设计 > UI/UE

IOS开发-NSNumber、NSValue、NSData的区别

2016-03-08 14:45 351 查看

简单介绍

我们在编码的时候,有时候需要将C里面原生的数据封装成对象,这样才能将其打包进NSDictionary或者NSArray进行存储或者其他操作;又譬如有时候需要存储结构体、图片等数据。OC给我们提供了一些相关接口,比较常见的是NSNumber、NSValue和NSData;

NSNumber

NSNumber主要是用来封装ANSI C内置的数据,比如char,float,int等等,相关方法如下:

封装:

+ (NSNumber *)numberWithChar:(char)value;
+ (NSNumber *)numberWithUnsignedChar:(unsigned char)value;
+ (NSNumber *)numberWithShort:(short)value;
+ (NSNumber *)numberWithUnsignedShort:(unsigned short)value;
+ (NSNumber *)numberWithInt:(int)value;
+ (NSNumber *)numberWithUnsignedInt:(unsigned int)value;
+ (NSNumber *)numberWithLong:(long)value;
+ (NSNumber *)numberWithUnsignedLong:(unsigned long)value;
+ (NSNumber *)numberWithLongLong:(long long)value;
+ (NSNumber *)numberWithUnsignedLongLong:(unsigned long long)value;
+ (NSNumber *)numberWithFloat:(float)value;
+ (NSNumber *)numberWithDouble:(double)value;
+ (NSNumber *)numberWithBool:(BOOL)value;
+ (NSNumber *)numberWithInteger:(NSInteger)value;
+ (NSNumber *)numberWithUnsignedInteger:(NSUInteger)value;


解封:

@property (readonly) char charValue;
@property (readonly) unsigned char unsignedCharValue;
@property (readonly) short shortValue;
@property (readonly) unsigned short unsignedShortValue;
@property (readonly) int intValue;
@property (readonly) unsigned int unsignedIntValue;
@property (readonly) long longValue;
@property (readonly) unsigned long unsignedLongValue;
@property (readonly) long long longLongValue;
@property (readonly) unsigned long long unsignedLongLongValue;
@property (readonly) float floatValue;
@property (readonly) double doubleValue;
@property (readonly) BOOL boolValue;
@property (readonly) NSInteger integerValue;
@property (readonly) NSUInteger unsignedIntegerValue;


用法如下:

NSNumber *intNum = [NSNumber numberWithInt:10];  //封装
int num = [intNum intValue];                      //解封


封装C类型数据还有一些简单写法:

NSNumber *intNum = @(10);  //@(原始数据)


NSValue

NSValue主要用来封装自定义的数据结构,可以是系统框架提供的CGRect/CGPoint/CGSize等数据结构,也可以是自己定义的struct。

主要封装及解封方法:

- (instancetype)initWithBytes:(const void *)value objCType:(const char *)type;

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


用法如下:

typedef struct people{
char *name;
int age;
}People;  //定义了一个结构体

People me = {"lotheve",21};
NSValue *value = [[NSValue alloc]initWithBytes:&me objCType:@encode(People)];  //封装
People person;
[value getValue:&person];  //解封


PS:@encode()用于获取数据类型,下面会介绍。

系统对CGRect、CGPoint、CGSize、CGAffineTransform等结构体封装好了方法:

封装:

+ (NSValue *)valueWithCGPoint:(CGPoint)point;
+ (NSValue *)valueWithCGVector:(CGVector)vector;
+ (NSValue *)valueWithCGSize:(CGSize)size;
+ (NSValue *)valueWithCGRect:(CGRect)rect;
+ (NSValue *)valueWithCGAffineTransform:(CGAffineTransform)transform;
+ (NSValue *)valueWithUIEdgeInsets:(UIEdgeInsets)insets;
+ (NSValue *)valueWithUIOffset:(UIOffset)insets;


解封:

- (CGPoint)CGPointValue;
- (CGVector)CGVectorValue;
- (CGSize)CGSizeValue;
- (CGRect)CGRectValue;
- (CGAffineTransform)CGAffineTransformValue;
- (UIEdgeInsets)UIEdgeInsetsValue;
- (UIOffset)UIOffsetValue;


说明:

需要指出一下,NSNumber实际上是NSValue的一个特殊情况,所以在类关系中,NSNumber是NSValue的子类

NSData

NSData主要是提供一块原始数据的封装,方便数据的封装与流动,比较常见的是NSString、UIImage数据的封装与传递。在应用中,最常用于访问存储在文件中或者网络资源中的数据。

该类的封装和解封方法如下:

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

- (NSUInteger)length;

- (const void *)bytes


从这几个方法可以看出来,NSData其实是对一段内存的打包,封装是只需提供初始地址和长度就行,它根本不管这段内存表示的是什么数据。

打包一个字符串:

NSString *str = @"this is a demo";
//对这一字符串进行打包
NSData *data = [NSData dataWithBytes:[str UTF8String] length:str.length+1];
//从data中取出字符串,只需这样写
NSString *string = [NSString stringWithUTF8String:[data bytes]];


系统已经封装好了大量方法:

对字符串的打包:

NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];


对图片的打包:

NSData *data = UIImagePNGRepresentation(image);
NSData *data = UIImageJPEGRepresentation(image, 0.5); //第二个参数为压缩比


对本地资源的打包:

NSData *data = [NSData dataWithContentsOfFile:filePath];
NSData *data = [NSData dataWithContentsOfURL:fileURL];


and so on!

@encode关键字

对于NSNumber,有时候会有这样一种需求:判断一个NSNumber对象封装的原始数据的类型。该怎么做呢? 这就不得不介绍一个关键字:@encode

@encode()的作用是传入一个数据类型,返回该类型的C字符串(char *)表示。这个数据类型可以是任何类型,可以是ANSI C的数据类型、自定义类型,还可以是函数或方法的元类型。另外,NSValue类提供了一个接口,可以获取被封装数据的数据类型的C字符串表示,NSNumber作为其子类同样拥有该接口。这样,我们只要对比两个数据类型就能判断是那种原始数据类型的封装。

代码示例如下:

NSArray *array = @[[NSNumber numberWithInt:10],[NSNumber numberWithFloat:10.0],[NSNumber numberWithBool:YES],[NSNumber numberWithChar:'x']];
for (int i = 0; i<array.count; i++) {
if ([array[i] isKindOfClass:[NSNumber class]]) {
NSNumber *num = array[i];
NSLog(@"%@",num);
const char *numType = num.objCType;
if (strcmp(numType, @encode(int)) == 0) {
NSLog(@"Type: int");
}else if (strcmp(numType, @encode(float)) == 0){
NSLog(@"Type: float");
}else if (strcmp(numType, @encode(double)) == 0){
NSLog(@"Type: double");
}else if (strcmp(numType, @encode(char)) == 0){
NSLog(@"Type: char");
}
}
}

/*
需要注意的是BOOL类型不能直接比较strcmp(numType, @encode(BOOL)),原因是早起BOOL被定义为signed char,numType结果为‘c’;而@encode(BOOL)结果为B,@encode(char)结果则是‘c’。因此BOOL类型是作为char类型被判断的。
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ios