系列:iOS开发-NSNumber、NSData

时间:2021-12-24 08:11:49

系列:iOS开发-NSNumber、NSData

这两个类型准备一起讲,
因为NSNumber比较简单,
首先将NSNumber,
我在之前就有说过在数组里面在字典里面是没有办法存储C语言中的那些基础类型的,比如int、比如float…
那么我们又想存储这些值 我们怎么办呢?
OC给我们封装了一个NSNumber的类
介绍就是:NSNumber:专门用来装基础类型的对象,把整型、单精度、双精度、字符型等基础类型存储为对象

基础类型->对象类型
那么就满足OC的语法,数组就可以存储了
所以说,NSNumber还是一个数…

我们简单看看这个类,

创建:

//NSNumber
//initWithChar:
NSNumber *num1 = [[NSNumber alloc]initWithChar:'a'];
NSLog(@"num1 = %@",num1);

//initWithShort:
NSNumber *num2= [[NSNumber alloc]initWithShort:1];
NSLog(@"num2 = %@",num2);

NSNumber *num3= [[NSNumber alloc]initWithInt:1];
NSLog(@"num3 = %@",num3);

//initWithLong:
NSNumber *num4 = [[NSNumber alloc]initWithLong:10000000000];
NSLog(@"num4 = %@",num4);

//initWithLongLong:
NSNumber *num5 = [[NSNumber alloc]initWithLongLong:1000000000000000000];
NSLog(@"num5 = %@",num5);

//initWithFloat:
NSNumber *num6 = [[NSNumber alloc]initWithFloat:M_PI];
NSLog(@"num6 = %@",num6);

//initWithDouble:
NSNumber *num7 = [[NSNumber alloc]initWithDouble:999999999999];
NSLog(@"num7 = %@",num7);

//initWithBool:
NSNumber *num8 = [[NSNumber alloc]initWithBool:YES];
NSLog(@"num8 = %@",num8);

//initWithInteger:
NSNumber *num9 = [[NSNumber alloc]initWithInteger:1];
NSLog(@"num9 = %@",num9);

NSNumber *num10 = @(111);
NSLog(@"num10 = %@",num10);

//numberWithChar:
NSNumber *num11 = [NSNumber numberWithChar:'b'];
NSLog(@"num11 = %@",num11);

//numberWithShort:
NSNumber *num12 = [NSNumber numberWithShort:1];
NSLog(@"num12 = %@",num12);

//numberWithInt:
NSNumber *num13 = [NSNumber numberWithInt:1];
NSLog(@"num13 = %@",num13);

//numberWithLong:
NSNumber *num14 = [NSNumber numberWithLong:1000000000];
NSLog(@"num14 = %@",num14);

//numberWithLongLong:
NSNumber *num15 = [NSNumber numberWithLongLong:10000000000000000];
NSLog(@"num15 = %@",num15);

//numberWithFloat:
NSNumber *num16 = [NSNumber numberWithFloat:M_PI];
NSLog(@"num16 = %@",num16);

//numberWithDouble:
NSNumber *num17 = [NSNumber numberWithDouble:999999999];
NSLog(@"num17 = %@",num17);

//numberWithBool:
NSNumber *num18 = [NSNumber numberWithBool:YES];
NSLog(@"num18 = %@",num18);

//numberWithInteger:
NSNumber *num19 = [NSNumber numberWithInteger:1];
NSLog(@"num19 = %@",num19);

我去….本来说简单,,但是所有的都写出来,真累………

常用方法
我们看看他有那些,然后一个一个来,

@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 NS_AVAILABLE(10_5, 2_0);
@property (readonly) NSUInteger unsignedIntegerValue NS_AVAILABLE(10_5, 2_0);

@property (readonly, copy) NSString *stringValue;

- (NSComparisonResult)compare:(NSNumber *)otherNumber;

- (BOOL)isEqualToNumber:(NSNumber *)number;

- (NSString *)descriptionWithLocale:(nullable id)locale;

首先的都是value 获取都原始的基础数据类型
然后是比较,
OK
我们一个一个试试

NSLog(@"%c",[num1 charValue]);

NSLog(@"%d",[num2 shortValue]);

NSLog(@"%d",[num3 intValue]);

NSLog(@"%ld",[num4 longValue]);

NSLog(@"%lld",[num5 longLongValue]);

NSLog(@"%f",[num6 floatValue]);

NSLog(@"%f", [num7 doubleValue]);

NSLog(@"%d",[num8 boolValue]);

NSLog(@"%ld",[num9 integerValue]);

NSLog(@"%@",[num10 stringValue]);

NSLog(@"%d",[num10 isEqualToNumber:num9]);

NSLog(@"%ld",(long)[num10 compare:num9]);

当然,并不是只能返回原始的基础类型,比如我原来的是float ,但是我用intValue会怎么样呢?没有错,强制转换了,转成int类型的数据了, 是的所以他还有强制转换的作用哟..

至于isEqualToNumber和compare都是比较两个对象的大小或者是否相等等问题

都是字面上的理解 超级简单….

所以NSNumber可以说的也不多,我们就这么随随便便的就基本掌握了一个类,
是不是很有成就感,

那么我们接下来就再看一个稍微复杂的类NSData
为什么说复杂了呢?

/**************** Immutable Data ****************/

@interface NSData : NSObject <NSCopying, NSMutableCopying, NSSecureCoding>

从定义上看,它也就是集成NSData的一个类型嘛….

+ (instancetype)data;
+ (instancetype)dataWithBytes:(nullable const void *)bytes length:(NSUInteger)length;
+ (instancetype)dataWithBytesNoCopy:(void *)bytes length:(NSUInteger)length;
+ (instancetype)dataWithBytesNoCopy:(void *)bytes length:(NSUInteger)length freeWhenDone:(BOOL)b;
+ (nullable instancetype)dataWithContentsOfFile:(NSString *)path options:(NSDataReadingOptions)readOptionsMask error:(NSError **)errorPtr;
+ (nullable instancetype)dataWithContentsOfURL:(NSURL *)url options:(NSDataReadingOptions)readOptionsMask error:(NSError **)errorPtr;
+ (nullable instancetype)dataWithContentsOfFile:(NSString *)path;
+ (nullable instancetype)dataWithContentsOfURL:(NSURL *)url;
- (instancetype)initWithBytes:(nullable const void *)bytes length:(NSUInteger)length;
- (instancetype)initWithBytesNoCopy:(void *)bytes length:(NSUInteger)length;
- (instancetype)initWithBytesNoCopy:(void *)bytes length:(NSUInteger)length freeWhenDone:(BOOL)b;
- (instancetype)initWithBytesNoCopy:(void *)bytes length:(NSUInteger)length deallocator:(nullable void (^)(void *bytes, NSUInteger length))deallocator NS_AVAILABLE(10_9, 7_0);
- (nullable instancetype)initWithContentsOfFile:(NSString *)path options:(NSDataReadingOptions)readOptionsMask error:(NSError **)errorPtr;
- (nullable instancetype)initWithContentsOfURL:(NSURL *)url options:(NSDataReadingOptions)readOptionsMask error:(NSError **)errorPtr;
- (nullable instancetype)initWithContentsOfFile:(NSString *)path;
- (nullable instancetype)initWithContentsOfURL:(NSURL *)url;
- (instancetype)initWithData:(NSData *)data;
+ (instancetype)dataWithData:(NSData *)data;

我们看下它的初始化和赋值等…
我们会发现一个bytes
这个又是什么鬼?其实就是这个东西
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};
或者Byte byte2[] = {0x01,0x02};
是的,就是个比特数组, 这玩意又回到了C的时候了好像,如果C语言没有学好,咋一看都会吓一跳,后面还有什么length?这个怎么算?对了 sizeof(byte)
好吧,这些都吓不到你,那么为什么我还说稍微复杂呢?那就是这个数据的性质吧,data打印出来,那就是很对什么都看不懂的数据或者一堆数字,
是的,你想到了编码ASCII、UTF8、BASE64… 没有错,这还涉及到编码,如果编码错了那就毫无意义…
光说好像没有什么感觉
那就用例子说话,
首先是创建

//NSData
//init
NSData *data1 = [[NSData alloc]init];
NSLog(@"data1 = %@",data1);

//initWithBytes:length:
Byte mybyte[] = {0x01,0x02,0x03};
NSData *data2 = [[NSData alloc]initWithBytes:mybyte length:sizeof(mybyte)];
NSLog(@"data2 = %@",data2);

//dataWithData:
NSData *data3 = [NSData dataWithData:data2];
NSLog(@"data3 = %@",data3);

没啥可以说的,那么该说的是什么呢?
没有错,就是NSData到各种类型的转换,因为我们很多时候拿着NSData没有什么用,因为不是具体的方便操作的类型….
首先我们看看转码的类型枚举

typedef NSUInteger NSStringEncoding;
NS_ENUM(NSStringEncoding) {
NSASCIIStringEncoding = 1, /* 0..127 only */
NSNEXTSTEPStringEncoding = 2,
NSJapaneseEUCStringEncoding = 3,
NSUTF8StringEncoding = 4,
NSISOLatin1StringEncoding = 5,
NSSymbolStringEncoding = 6,
NSNonLossyASCIIStringEncoding = 7,
NSShiftJISStringEncoding = 8, /* kCFStringEncodingDOSJapanese */
NSISOLatin2StringEncoding = 9,
NSUnicodeStringEncoding = 10,
NSWindowsCP1251StringEncoding = 11, /* Cyrillic; same as AdobeStandardCyrillic */
NSWindowsCP1252StringEncoding = 12, /* WinLatin1 */
NSWindowsCP1253StringEncoding = 13, /* Greek */
NSWindowsCP1254StringEncoding = 14, /* Turkish */
NSWindowsCP1250StringEncoding = 15, /* WinLatin2 */
NSISO2022JPStringEncoding = 21, /* ISO 2022 Japanese encoding for e-mail */
NSMacOSRomanStringEncoding = 30,

NSUTF16StringEncoding = NSUnicodeStringEncoding, /* An alias for NSUnicodeStringEncoding */

NSUTF16BigEndianStringEncoding = 0x90000100, /* NSUTF16StringEncoding encoding with explicit endianness specified */
NSUTF16LittleEndianStringEncoding = 0x94000100, /* NSUTF16StringEncoding encoding with explicit endianness specified */

NSUTF32StringEncoding = 0x8c000100,
NSUTF32BigEndianStringEncoding = 0x98000100, /* NSUTF32StringEncoding encoding with explicit endianness specified */
NSUTF32LittleEndianStringEncoding = 0x9c000100 /* NSUTF32StringEncoding encoding with explicit endianness specified */
}

是不是眼花缭乱了?

没有错,如果用的编码方式不一样,结果就不一样,就不是你想要的
比如你看看
系列:iOS开发-NSNumber、NSData

结果就有的不一样…当然这个是最简单的例子,我们是需要自实际中选择合适的编码规则的,所以也不需要太过担心…

//常用转换
//NSData->NSString
NSString *str1 = [[NSString alloc] initWithData:data3 encoding:NSUTF16StringEncoding];
NSLog(@"%@",str1);

NSString *str2 = [[NSString alloc] initWithData:data3 encoding:NSUTF8StringEncoding];
NSLog(@"%@",str2);

//NSString->NSData
NSString *str3 = @"1234abcd";
NSData *date4 = [str3 dataUsingEncoding: NSUTF8StringEncoding];
NSLog(@"date4 = %@",date4);

//NSData->Byte数组
NSString *str4 = @"1234567890";
NSData *date5 = [str4 dataUsingEncoding: NSUTF8StringEncoding];
Byte *byte2 = (Byte *)[date5 bytes];
for(int i=0;i<[date5 length];i++){
printf("byte2 = %d\n",byte2[i]);
}

//Byte数组->NSData
Byte byte3[] = {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 *data6 = [[NSData alloc] initWithBytes:byte3 length:sizeof(byte3)];
NSLog(@"data6 = %@",data6);

//Byte数组->16进制数
Byte *bytes = (Byte *)[data6 bytes];
NSString *hexStr=@"";
for(int i=0;i<[data6 length];i++)
{
NSString *newHexStr = [NSString stringWithFormat:@"%x",bytes[i]&0xff]; ///16进制数
if([newHexStr length]==1)
hexStr = [NSString stringWithFormat:@"%@0%@",hexStr,newHexStr];
else
hexStr = [NSString stringWithFormat:@"%@%@",hexStr,newHexStr];
}
NSLog(@"bytes 的16进制数为:%@",hexStr);


//16进制数->Byte数组
/// 将16进制数据转化成Byte 数组
NSString *hexString = @"3e435fab9c34891f"; //16进制字符串
int j=0;
Byte bytes1[128];
///3ds key的Byte 数组, 128位
for(int i=0;i<[hexString length];i++)
{
int int_ch; /// 两位16进制数转化后的10进制数

unichar hex_char1 = [hexString characterAtIndex:i]; ////两位16进制数中的第一位(高位*16)
int int_ch1;
if(hex_char1 >= '0' && hex_char1 <='9')
int_ch1 = (hex_char1-48)*16; //// 0 的Ascll - 48
else if(hex_char1 >= 'A' && hex_char1 <='F')
int_ch1 = (hex_char1-55)*16; //// A 的Ascll - 65
else
int_ch1 = (hex_char1-87)*16; //// a 的Ascll - 97
i++;

unichar hex_char2 = [hexString characterAtIndex:i]; ///两位16进制数中的第二位(低位)
int int_ch2;
if(hex_char2 >= '0' && hex_char2 <='9')
int_ch2 = (hex_char2-48); //// 0 的Ascll - 48
else if(hex_char1 >= 'A' && hex_char1 <='F')
int_ch2 = hex_char2-55; //// A 的Ascll - 65
else
int_ch2 = hex_char2-87; //// a 的Ascll - 97

int_ch = int_ch1+int_ch2;
NSLog(@"int_ch=%d",int_ch);
bytes[j] = int_ch; ///将转化后的数放入Byte数组里
j++;
}
NSData *newData = [[NSData alloc] initWithBytes:bytes1 length:sizeof(bytes1)];
NSLog(@"newData=%@",newData);

总之由于数据类型的关系,NSData有时候需要做位运算,这些在遇到的时候再说吧.当然有的人可能几年都遇不到….
至于可变data—— NSMutableData就简单的看看方法就行了,大家可以自己去尝试看看

- (void)appendBytes:(const void *)bytes length:(NSUInteger)length;
- (void)appendData:(NSData *)other;
- (void)increaseLengthBy:(NSUInteger)extraLength;
- (void)replaceBytesInRange:(NSRange)range withBytes:(const void *)bytes;
- (void)resetBytesInRange:(NSRange)range;
- (void)setData:(NSData *)data;
- (void)replaceBytesInRange:(NSRange)range withBytes:(nullable const void *)replacementBytes length:(NSUInteger)replacementLength;

首先是追加bytes
然后是追加新的NSData
再接下来的就是一些设置,替换等方法………
这里就不一一赘述了

Demo地址:https://github.com/spicyShrimp/DEMO_OC

系列:iOS开发-前言+大纲
http://blog.csdn.net/spicyShrimp/article/details/62218521