系列:iOS开发-NSNumber、NSData

1,296 阅读8分钟

#系列: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 */
}

是不是眼花缭乱了?

没有错,如果用的编码方式不一样,结果就不一样,就不是你想要的 比如你看看

这里写图片描述

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

//常用转换
        //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地址:github.com/spicyShrimp…

系列:iOS开发-前言+大纲 blog.csdn.net/spicyShrimp…