跟着苹果API学习NSData

作者两年iOS开发经验,通过阅读苹果api重温各个知识点,如果你喜欢这个系列,请关注我。有任何建议请留言。转载请注明来源。
本来这个系列只是单纯的苹果api学习笔记,后来想学习一下YYKit的源码,所以在文章中一并加入

作者:Roger


1. Creating Data Objcets[创建Data对象]

首先来看苹果提供给我们创建Data对象的其中三个方法

//创建并返回一个空data对象
+ data

- initWithData:

//根据length大小,创建并返回一个限定字节的data对象
+ dataWithBytes:length:



实验了一下不同情况下NSData的输出结果:
1.如果创建一个空的data,输出的结果也都为空。

NSData *data1 = [NSData data];
NSLog(@"%@,%ld,%@",data1,data1.length,data1.description);
//输出结果: <>,0,<>

NSString *str1 = [[NSString alloc]initWithData:data1 encoding:NSUTF8StringEncoding];
NSLog(@"%@",str1);
//输出结果:



2.通过dataWithBytes:length:创建data,并且data的length等于内容的大小。
*为什么用NSASCIIStringEncoding时,输出中文会得到乱码?
*ASCII,Unicode和UTF-8的区别

const char *string = "Hi there ,this is a C string我了个去";
NSData *data2 = [NSData dataWithBytes:string length:strlen(string)];
NSLog(@"%@,%ld,%@",data2,data2.length,data2.description);
//输出结果:<48692074 68657265 202c7468 69732069 73206120 43207374 72696e67 e68891e4 ba86e4b8 aae58ebb>,40,<48692074 68657265 202c7468 69732069 73206120 43207374 72696e67 e68891e4 ba86e4b8 aae58ebb>    

//utf8和ascii区别?
NSString *str2 = [[NSString alloc]initWithData:data2 encoding:NSUTF8StringEncoding];
NSString *str22 = [[NSString alloc]initWithData:data2 encoding:NSASCIIStringEncoding];
NSLog(@"str2 = %@,str11 = %@",str2,str22);
//输出结果:str2 = Hi there ,this is a C string****我了个去****,str11 = Hi there ,this is a C stringæ��äº�个å�»



3.通过dataWithBytes:length:创建data,并且data的length小于内容的大小。可以发现,如果length小于data的实际大小,输出的结果为空。

NSData *data3 = [NSData dataWithBytes:string length:strlen(string - 1)];
NSLog(@"%@,%ld,%@",data3,data3.length,data3.description);
//输出结果: <>,0,<>
NSString *str3 = [[NSString alloc]initWithData:data3 encoding:NSUTF8StringEncoding];
NSLog(@"str3 = %@",str3);
//输出结果:str3 =



3.通过dataWithBytes:length:创建data,并且data的length大于内容的大小。如果length大于data的实际大小,大于多少位,输出的字符就缺少多少位。

NSData *data4 = [NSData dataWithBytes:string length:strlen(string + 5)];
NSLog(@"%@,%ld,%@",data4,data4.length,data4.description);
//输出结果:<48692074 68657265 202c7468 69732069 73206120 43207374 72696e67 e68891e4 ba86e4b8 aae58ebb>,40,<48692074 68657265 202c7468 69732069 73206120 43207374 72696e67 e68891e4 ba86e4>    

 NSString *str4 = [[NSString alloc]initWithData:data4 encoding:NSUTF8StringEncoding];
    NSLog(@"str4 = %@",str4);
//输出结果:str4 = nil

总结:

  1. 如果通过方法dataWithBytes:length:创建data时,length的大小小于实际内容大小时,会创建一个byte为0的data对象。通过data转string,输出为空。
  2. 如果length的大小大于实际内容大小时,大于多少位,输出data的字符就缺少多少位。通过data转string,输出为nil。



接着我们再来看另外两个创建Data对象的方法:

+ dataWithBytesNoCopy:length:

+ dataWithBytesNoCopy:length:freeWhenDone:

在使用dataWithBytesNoCopy:length:创建data对象时,会有崩溃发生:

malloc: *** error for object 0x10f344665: pointer being freed was not allocated**
***** set a breakpoint in malloc_error_break to debug

大概搜索了一下原因,对这里的了解似懂非懂,暂留坑,总之在没搞清楚这里的情况下,最好按照下面的回答说的,使用dataWithBytes来创建data对象。

屏幕快照 2016-08-31 下午3.05.14.png




两个通过地址创建data对象的方法:

//根据地址创建data对象
+ dataWithContentsOfFile:

//根据地址创建data对象,并根据枚举类型操作data
+ dataWithContentsOfFile:options:error:

typedef NS_OPTIONS(NSUInteger, NSDataReadingOptions) {
    //使用这个参数后,iOS就不会把整个文件全部读取的内存了,而是将文件映射到进程的地址空间中。
    //这么做并不会占用实际内存。这样就可以解决内存满的问题。
    NSDataReadingMappedIfSafe = 1UL << 0,
    //数据将不会存入内存中,对于只会使用一次的数据,这么做会提高性能。
    NSDataReadingUncached = 1UL << 1,
    //数据始终会被存储在内存中,如果用户定义了NSDataReadingMappedIfSafe和这个枚举,那么这个枚举会优先起作用。
    NSDataReadingMappedAlways NS_ENUM_AVAILABLE(10_7, 5_0) = 1UL << 3, 
    
    //老枚举,苹果建议不再使用。
    NSDataReadingMapped = NSDataReadingMappedIfSafe, // Deprecated name for NSDataReadingMappedIfSafe
    NSMappedRead = NSDataReadingMapped,   // Deprecated name for NSDataReadingMapped
    NSUncachedRead = NSDataReadingUncached  // Deprecated name for NSDataReadingUncached
};

类似上面的方法,还有通过url创建data对象的方法,在视频播放方面会用到这个方法

- initWithContentsOfURL:

- initWithContentsOfURL:options:error:

2. Accessing Data[访问Data对象]

  • bytes

    属性,如果Data的length为0,此方法返回nil。

  • description

属性,一个十六进制字符串,包含在属性列表格式的对象的内容表示。(只读)

  • -enumeraterByteRangesUsingBlock:
    NSData 对象如果是由许多不同的对象组合而成,因此可以使用 NSData 的 enumerateByteRangesUsingBlock: 来遍历数据。
  • -getBytes:
  • -getBytes:length:
  • -getBytes:range:

接收数据,复制所给范围内字节到一个给定的缓冲区中。

  • -subdataWithRange:

    返回包含在给定范围内的数据对象。

  • -rangeOfData:options:range:

在给定的范围内,以给定的选项,查找并返回给定数据的第一个发生的范围。

3. Base-64 Encoding

填坑...

Testing Data

  • -isEqualToData:
    对比data

*##### length
属性,data的数量

4. Storing Data

  • -writeToFile:atomically:

将接收到的字节写入给定路径指定的文件。
atomically这个参数意思是,如果为YES则保证文件的写入原子性,就是说会先创建一个临时文件,直到文件内容写入成功再导入到目标文件里。 如果为NO,则直接写入目标文件里。

  • -writeToFile:options:error:
typedef NS_OPTIONS(NSUInteger, NSDataWritingOptions) {
    //等同于上面的atomically == YES
    NSDataWritingAtomic = 1UL << 0, 
    //如果已存在文件,则不会覆盖原文件,写入失败。
    NSDataWritingWithoutOverwriting NS_ENUM_AVAILABLE(10_8, 6_0) = 1UL << 1, 
    //資源沒有與其相關聯的特殊保護。任何時候都可以讀取或寫入資源
    NSDataWritingFileProtectionNone NS_ENUM_AVAILABLE_IOS(4_0)                                  = 0x10000000,
    //資源會以加密格式儲存在磁碟,當裝置處於鎖定狀態或者正在開機時,將無法進行讀取或寫入。
    NSDataWritingFileProtectionComplete NS_ENUM_AVAILABLE_IOS(4_0)                              = 0x20000000,
    //資源會以加密格式儲存在磁碟。當裝置處於鎖定狀態時,可以建立資源,但是一旦關閉資源,就無法再次開啟,直到裝置解除鎖定。如果在解除鎖定時開啟了資源,則可以如常繼續存取資源,即使使用者鎖定了裝置也無妨。
    NSDataWritingFileProtectionCompleteUnlessOpen NS_ENUM_AVAILABLE_IOS(5_0)                    = 0x30000000,
    //資源會以加密格式儲存在磁碟,只有在裝置開機之後,才能存取資源。在使用者首次解除鎖定裝置之後,您的應用程式可以存取資源,即使使用者之後鎖定了裝置,還是可以繼續存取。
    NSDataWritingFileProtectionCompleteUntilFirstUserAuthentication NS_ENUM_AVAILABLE_IOS(5_0)  = 0x40000000,
    NSDataWritingFileProtectionMask NS_ENUM_AVAILABLE_IOS(4_0)                                  = 0xf0000000,

    //不建议再使用
    NSAtomicWrite = NSDataWritingAtomic     // Deprecated name for NSDataWritingAtomic
};
  • -writeToUrl:atomically:

填坑...

  • -writeToUrl:options:error:

填坑...

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,036评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,046评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,411评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,622评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,661评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,521评论 1 304
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,288评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,200评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,644评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,837评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,953评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,673评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,281评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,889评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,011评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,119评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,901评论 2 355

推荐阅读更多精彩内容