值对象(value object)概念
在面向对象的编程语言中,值对象本质上是数据元素的的对象包装器,所谓数据元素,常见的包含string,number,date类型以及其它自定义的结构体类型。Objective-C语言本身提供了string,number,date相对应的包装类,分别是NSString,NSNumber,NSDate,这些类创建的对象都可以称为值对象。但值对象本身的范围更加广泛,它可以是任何自定义类型创建的对象。
值对象作用
C语言提供了char/int/float/double基本数据类型,基于C语言的Objective-C因此同样包含了这几种基本数据类型,我们可以定义并使用这些基本数据类型的变量,也可以使用其对应的值对象,对于自定义数据类型,我们也可以将由这些类型定义的变量通过NSValue来包装成对象类型。相对于普通的变量,值对象提供了更多的功能和作用。
1.可将任何值对象存储在集合中。
在Objective-C中,诸如NSArray,NSDictionary这样的集合类所包含的元素必须是对象类型。因此基本数据类型的变量必须转换为值对象才能存储在集合中。
2.更加更加丰富的数据处理方法。
NSString或NSMulableString可以进行一系列针对字符串的操作,如字符串的连接,分割,查找,比较,提取字符等等。
NSDate和NSCaleder可进行复杂的日期处理和计算,所有这些计算都考虑了时区和闰年的影响。
NSNumber和NSDecimalNumber可以处理 char, short int, int, long int, long long int, float, or double , BOOL值,并提供了数值与字符串的转换
NSValue释义
上面我们已经提到NSValue可包装基本数据类型为对象类型,下面我们来看下Apple官方文档释义:
NSValue提供了简单的容器来包含C或Objective-C数据项。可以容纳任何基本数据类型如char,int,float,double,以及指针,结构体和对象ids。NSArray和NSSet集合类对象要求它们的元素为对象类型,NSValue的主要目的是使这些数据类型可以添加至集合中。NSValue对象是不可变类型。
简而言之,NSValue是基本数据类型或自定义数据类型所定义变量的对象包装器。
使用NSValue
1.处理NSRange,方法
如,
2.处理自定义结构体类型,方法
如:
自定义类型必须是固定长度类型,不能将C字符串,可变长度的数组和结构体,以及其它变长类型存储在NSValue中,这些可变类型应该使用NSString或NSData来包装成对象类型。但可以将可变数据类型的指针保存在NSValue中,官方文档示例:
原意想要保存myCString到NSValue中,但实际上myCString是以char的指针类型进行解析的,所以字符串的前四个字节被当做了指针的值,而不是地址值来对待。
正确的做法是保存字符串到NSString中,如,
或者,保存该字符串的指针地址到NSValue中,如,
3.处理指针类型,方法
如:
NSValue的分类
UIKit Additions
提供了Function框架中关于几何数据类型结构体的对象值包装,包括CGPoint,CGRect,CGSize,CGAffineTransform,UIEdgeInsets,UIOffset。
以CGPoint为例(其它的结构体都有相对应的方法),方法
如:
Core Animation Additions
在面向对象的编程语言中,值对象本质上是数据元素的的对象包装器,所谓数据元素,常见的包含string,number,date类型以及其它自定义的结构体类型。Objective-C语言本身提供了string,number,date相对应的包装类,分别是NSString,NSNumber,NSDate,这些类创建的对象都可以称为值对象。但值对象本身的范围更加广泛,它可以是任何自定义类型创建的对象。
值对象作用
C语言提供了char/int/float/double基本数据类型,基于C语言的Objective-C因此同样包含了这几种基本数据类型,我们可以定义并使用这些基本数据类型的变量,也可以使用其对应的值对象,对于自定义数据类型,我们也可以将由这些类型定义的变量通过NSValue来包装成对象类型。相对于普通的变量,值对象提供了更多的功能和作用。
1.可将任何值对象存储在集合中。
在Objective-C中,诸如NSArray,NSDictionary这样的集合类所包含的元素必须是对象类型。因此基本数据类型的变量必须转换为值对象才能存储在集合中。
2.更加更加丰富的数据处理方法。
NSString或NSMulableString可以进行一系列针对字符串的操作,如字符串的连接,分割,查找,比较,提取字符等等。
NSDate和NSCaleder可进行复杂的日期处理和计算,所有这些计算都考虑了时区和闰年的影响。
NSNumber和NSDecimalNumber可以处理 char, short int, int, long int, long long int, float, or double , BOOL值,并提供了数值与字符串的转换
NSValue释义
上面我们已经提到NSValue可包装基本数据类型为对象类型,下面我们来看下Apple官方文档释义:
NSValue提供了简单的容器来包含C或Objective-C数据项。可以容纳任何基本数据类型如char,int,float,double,以及指针,结构体和对象ids。NSArray和NSSet集合类对象要求它们的元素为对象类型,NSValue的主要目的是使这些数据类型可以添加至集合中。NSValue对象是不可变类型。
简而言之,NSValue是基本数据类型或自定义数据类型所定义变量的对象包装器。
使用NSValue
1.处理NSRange,方法
1
2
|
+ (NSValue *)valueWithRange:(NSRange)range
- (NSRange)rangeValue
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
NSRange rangeA ;
rangeA.location = 0 ;
rangeA.location = 10 ;
// 创建NSRange的值对象
NSValue *rangeValue = [NSValue valueWithRange:rangeA] ;
// 重新获取值对象包含的值
NSRange rangeB = [rangeValue rangeValue] ;
NSLog(@
"%d,%d"
,rangeB.location , rangeB.length) ;
// 10,10
|
2.处理自定义结构体类型,方法
1
2
3
|
+ (NSValue *)valueWithBytes:(
const
void
*)value objCType:(
const
char
*)type
- (id)initWithBytes:(
const
void
*)value objCType:(
const
char
*)type
- (
void
)getValue:(
void
*)buffer
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
// 结构体定义
typedef
struct
{
int
a ;
float
b ;
}DataItem ;
DataItem dataElemA ;
dataElemA.a = 10 ;
dataElemA.b = 10.005 ;
NSValue *value = [NSValue valueWithBytes:&dataItem objCType:@encode(DataItem)] ;
DataItem dataElemB ;
[value getValue:&dataElemB] ;
NSLog(@
"%d,%0.3f"
,dataElemB.a,dataElemB.b);
// 10,10.005
|
原意想要保存myCString到NSValue中,但实际上myCString是以char的指针类型进行解析的,所以字符串的前四个字节被当做了指针的值,而不是地址值来对待。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
/* INCORRECT! */
char
*myCString =
"This is a string."
;
NSValue *theValue = [NSValue valueWithBytes:myCString objCType:@encode(
char
*)];
char
*cc = (
char
*)malloc(
sizeof
(
char
*)*200) ;
[theValue getValue:cc];
prinf(
"%s"
, cc) ;
// This
free(cc)
|
1
2
3
|
char
*myCString =
"This is a string."
;
NSString myNsString = [NSString stringWithCString:myCString encoding:NSUTF8StringEncoding] ;
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
char
*myCString =
"This is a string."
;
NSValue *theValue = [NSValue valueWithBytes:&myCString objCType:@encode(
char
**)];
char
**cc = (
char
**)
malloc
(
sizeof
(
char
**)*200) ;
[theValue getValue:cc];
printf
(
"----%s----"
, *cc);
// This is a string.
free
(cc) ;
cc = NULL ;
|
1
2
|
+ (NSValue *)valueWithPointer:(
const
void
*)aPointer
- (
void
*)pointerValue
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
DataItem *dd = (DataItem*)
malloc
(
sizeof
(DataItem)) ;
dd->a = 1 ;
dd->b = 2 ;
NSValue *pValue = [NSValue valueWithPointer:dd] ;
DataItem *dc = (DataItem*)[pValue pointerValue] ;
NSLog(@
"%d,%0.3f"
,dc->a,dc->b);
free
(dd) ;
dd = NULL ;
dc = NULL ;
|
NSValue的分类
UIKit Additions
提供了Function框架中关于几何数据类型结构体的对象值包装,包括CGPoint,CGRect,CGSize,CGAffineTransform,UIEdgeInsets,UIOffset。
以CGPoint为例(其它的结构体都有相对应的方法),方法
1
2
|
+ (NSValue *)valueWithCGPoint:(CGPoint)point
- (CGPoint)CGPointValue
|
1
2
3
4
5
6
7
8
9
|
CGPoint origin = CGPointMake(10.0 , 10.0) ;
NSValue *ptValue = [NSValue valueWithCGPoint:origin] ;
NSArray *ptArr = [NSArray arrayWithObject:ptValue];
NSValue *ptValueB = [ptArr objectAtIndex:0] ;
CGPoint originB = [ptValueB CGPointValue] ;
|
Core Animation Additions
提供CATransform3D结构体的对象值包装
MapKit Additions
提供CLLocationCoordinate2D和MKCoordinateSpan结构体的对象包装