zoukankan      html  css  js  c++  java
  • 结构体的转换

    值对象(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,方法 

    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

            自定义类型必须是固定长度类型,不能将C字符串,可变长度的数组和结构体,以及其它变长类型存储在NSValue中,这些可变类型应该使用NSString或NSData来包装成对象类型。但可以将可变数据类型的指针保存在NSValue中,官方文档示例: 
        
            原意想要保存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)

           正确的做法是保存字符串到NSString中,如, 

    1
    2
    3
    char *myCString = "This is a string.";
        
    NSString myNsString = [NSString stringWithCString:myCString encoding:NSUTF8StringEncoding] ;

           或者,保存该字符串的指针地址到NSValue中,如, 

    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 ;

            3.处理指针类型,方法 

    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] ;
  • 相关阅读:
    sql 将某列转换成一个字符串 for xml path用法
    IAsyncResult 接口异步 和 匿名委托
    存储过程和sql语句的优缺点
    ADO.net中常用的对象有哪些?分别描述一下。
    ASP.Net页面生命周期
    请说明在.net中常用的几种页面间传递参数的方法,并说出他们的优缺点。
    .net常用的传值的方法
    SQL列合并
    程序员的情书!
    程序员的表达!
  • 原文地址:https://www.cnblogs.com/loserof/p/4063651.html
Copyright © 2011-2022 走看看