Objective-C的Foundation框架——其他数值

NSArray和NSDictionary只能存储对象,不能直接存储任何基本类型的数据(如int、float和struct)。

但是我们可以用对象来封装基本数值,然后再放入NSArray和NSDictionary中。

如果想要使用对象来处理基本类型,就可以使用NSInteger和NSUInteger,这些类型也要针对32为和64位处理器对数值进行统一。

0x01 NSNumber

Cocoa提供了NSNumber类来封装基本数据类型。

使用类方法创建NSNumber对象

可以使用以下类方法来创建新的NSNumber对象(仅举部分例子):

+ (NSNumber *) numberWithChar: (char) value;
+ (NSNumber *) numberWithInt: (int) value;
+ (NSNumber *) numberWithFloat: (float) value;
+ (NSNumber *) numberWithBool: (BOOL) value;

//示例
int a = 1;
int x = 2;
float f = 3.456;
double d = 7.89;

//int   --->   obj
NSNumber *intObj = [NSNumber numberWithInt:a];
NSMutableArray *array = [NSMutableArray arrayWithObjects:intObj, nil];

//float ---> NSNumber
NSNumber *floatObj = [NSNumber numberWithFloat:f];
[array addObject:floatObj];


//double ---> NSNumber
NSNumber *doubleObj = [NSNumber numberWithDouble:d];
[array addObject:doubleObj];

使用字面量语法创建NSNumber对象

NSNumber *number;
number = @'X';         // char
number = @12345;       // integer
number = @12345ul;     // unsigned long
number = @12345ll;     // long long
number = @123.45f;     // float
number = @123.45;      // double
number = @YES;         // BOOL

从NSNumber中提取基本类型

将一个基本类型数据封装到NSNumber中后,我们可以通过一系列方法来重新获得它:

- (char) charValue;
- (int) intValue;
- (float) floatValue;
- (BOOL) boolValue;
- (NSString *)stringValue;

将创建方法和提取方法搭配在一起使用是可以的,如果用numberWithFloat:方法创建了NSNumber对象,然后用intValue方法来提取数值,NSNumber会对数据进行适当的转换:

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        float f = 3.14;
        
        NSNumber *fnumber = [NSNumber numberWithFloat:f];
        NSLog(@"%@", fnumber);
        
        int i = [fnumber intValue];
        NSLog(@"%d", i);
        
    }
    return 0;
}

//Output:
//2018-07-27 01:20:16.457 test[1896:33403] 3.14
//2018-07-27 01:20:16.458 test[1896:33403] 3
//Program ended with exit code: 0
//

0x02 NSValue

前面提到的NSNumber实际上是NSValue的子类,NSValue主要用来封装自定义的数据结构。

可以是系统框架提供的CGRect/CGPoint/CGSize等数据结构,也可以是自己定义的struct。

NSValue提供了封装方法:

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

同时也提供了解封方法:

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

这里的方法名中出现了get!

它表明我们提供的是一个指针,而指针所指向的空间则是用来存放该方法生成的数据!

所以,看到这里应该明白,为什么前面的章节说,重写方法有set而不能有get!

《Objective-C继承(Inheritance)——重写方法》

下面是示例程序:

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        typedef struct testTag
        {
            int  a;
            char *b;
        }TEST_DATA_ST;
        
        TEST_DATA_ST stValue = {0};
        stValue.a = 58;
        stValue.b = "test";
        
        //封装struct
        NSValue *value = [NSValue valueWithBytes:&stValue objCType:@encode(TEST_DATA_ST)];   
        NSArray *array = [NSArray arrayWithObjects:value, nil];   //封装成value之后可以装入NSArray
        
        TEST_DATA_ST testValue = {0};
        [value getValue:&testValue];                              //解封value
        
        NSLog(@"%d, %s", testValue.a, testValue.b);
        
    }
    return 0;
}

//Output:
//2018-07-27 02:08:00.450 test[2311:56190] 58, test
//Program ended with exit code: 0
//

@encode是编译器指令之一,返回一个给定类型编码为一种内部表示的字符串(例如,@encode(int) → i)。

类似于 ANSI C 的 typeof 操作。

苹果的 Objective-C 运行时库(runtime)内部利用类型编码帮助加快消息分发。

针对很常见CGRect/CGPoint/CGSize等数据结构,NSValue也提供了封装好的接口:

//Boxing
+ (NSValue *)valueWithCGPoint:(CGPoint)point;
+ (NSValue *)valueWithCGSize:(CGSize)size;
+ (NSValue *)valueWithCGRect:(CGRect)rect;

//Unboxing
- (CGPoint)CGPointValue;
- (CGSize)CGSizeValue;
- (CGRect)CGRectValue;

0x03 NSNull

NSNull是一个类,它只有一个方法:

+ (NSNull *) null;

[NSNull null]用来在NSArray和NSDictionary中加入非nil(表示列表结束)的空值。

[NSNull null]是一个对象,用来表示空,用在不能使用nil的场合。

猜你喜欢

转载自blog.csdn.net/qq_33737036/article/details/81224197