跟著蘋果API學(xué)習(xí)NSData

作者兩年iOS開發(fā)經(jīng)驗(yàn),通過閱讀蘋果api重溫各個(gè)知識點(diǎn),如果你喜歡這個(gè)系列,請關(guān)注我。有任何建議請留言。轉(zhuǎn)載請注明來源。
本來這個(gè)系列只是單純的蘋果api學(xué)習(xí)筆記,后來想學(xué)習(xí)一下YYKit的源碼,所以在文章中一并加入

作者:Roger


1. Creating Data Objcets[創(chuàng)建Data對象]

首先來看蘋果提供給我們創(chuàng)建Data對象的其中三個(gè)方法

//創(chuàng)建并返回一個(gè)空data對象
+ data

- initWithData:

//根據(jù)length大小,創(chuàng)建并返回一個(gè)限定字節(jié)的data對象
+ dataWithBytes:length:



實(shí)驗(yàn)了一下不同情況下NSData的輸出結(jié)果:
1.如果創(chuàng)建一個(gè)空的data,輸出的結(jié)果也都為空。

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

NSString *str1 = [[NSString alloc]initWithData:data1 encoding:NSUTF8StringEncoding];
NSLog(@"%@",str1);
//輸出結(jié)果:



2.通過dataWithBytes:length:創(chuàng)建data,并且data的length等于內(nèi)容的大小。
*為什么用NSASCIIStringEncoding時(shí),輸出中文會得到亂碼?
*ASCII,Unicode和UTF-8的區(qū)別

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

//utf8和ascii區(qū)別?
NSString *str2 = [[NSString alloc]initWithData:data2 encoding:NSUTF8StringEncoding];
NSString *str22 = [[NSString alloc]initWithData:data2 encoding:NSASCIIStringEncoding];
NSLog(@"str2 = %@,str11 = %@",str2,str22);
//輸出結(jié)果:str2 = Hi there ,this is a C string****我了個(gè)去****,str11 = Hi there ,this is a C string????o???a???



3.通過dataWithBytes:length:創(chuàng)建data,并且data的length小于內(nèi)容的大小??梢园l(fā)現(xiàn),如果length小于data的實(shí)際大小,輸出的結(jié)果為空。

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



3.通過dataWithBytes:length:創(chuàng)建data,并且data的length大于內(nèi)容的大小。如果length大于data的實(shí)際大小,大于多少位,輸出的字符就缺少多少位。

NSData *data4 = [NSData dataWithBytes:string length:strlen(string + 5)];
NSLog(@"%@,%ld,%@",data4,data4.length,data4.description);
//輸出結(jié)果:<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);
//輸出結(jié)果:str4 = nil

總結(jié):

  1. 如果通過方法dataWithBytes:length:創(chuàng)建data時(shí),length的大小小于實(shí)際內(nèi)容大小時(shí),會創(chuàng)建一個(gè)byte為0的data對象。通過data轉(zhuǎn)string,輸出為空。
  2. 如果length的大小大于實(shí)際內(nèi)容大小時(shí),大于多少位,輸出data的字符就缺少多少位。通過data轉(zhuǎn)string,輸出為nil。



接著我們再來看另外兩個(gè)創(chuàng)建Data對象的方法:

+ dataWithBytesNoCopy:length:

+ dataWithBytesNoCopy:length:freeWhenDone:

在使用dataWithBytesNoCopy:length:創(chuàng)建data對象時(shí),會有崩潰發(fā)生:

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

大概搜索了一下原因,對這里的了解似懂非懂,暫留坑,總之在沒搞清楚這里的情況下,最好按照下面的回答說的,使用dataWithBytes來創(chuàng)建data對象。

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




兩個(gè)通過地址創(chuàng)建data對象的方法:

//根據(jù)地址創(chuàng)建data對象
+ dataWithContentsOfFile:

//根據(jù)地址創(chuàng)建data對象,并根據(jù)枚舉類型操作data
+ dataWithContentsOfFile:options:error:

typedef NS_OPTIONS(NSUInteger, NSDataReadingOptions) {
    //使用這個(gè)參數(shù)后,iOS就不會把整個(gè)文件全部讀取的內(nèi)存了,而是將文件映射到進(jìn)程的地址空間中。
    //這么做并不會占用實(shí)際內(nèi)存。這樣就可以解決內(nèi)存滿的問題。
    NSDataReadingMappedIfSafe = 1UL << 0,
    //數(shù)據(jù)將不會存入內(nèi)存中,對于只會使用一次的數(shù)據(jù),這么做會提高性能。
    NSDataReadingUncached = 1UL << 1,
    //數(shù)據(jù)始終會被存儲在內(nèi)存中,如果用戶定義了NSDataReadingMappedIfSafe和這個(gè)枚舉,那么這個(gè)枚舉會優(yōu)先起作用。
    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創(chuàng)建data對象的方法,在視頻播放方面會用到這個(gè)方法

- initWithContentsOfURL:

- initWithContentsOfURL:options:error:

2. Accessing Data[訪問Data對象]

  • bytes

    屬性,如果Data的length為0,此方法返回nil。

  • description

屬性,一個(gè)十六進(jìn)制字符串,包含在屬性列表格式的對象的內(nèi)容表示。(只讀)

  • -enumeraterByteRangesUsingBlock:
    NSData 對象如果是由許多不同的對象組合而成,因此可以使用 NSData 的 enumerateByteRangesUsingBlock: 來遍歷數(shù)據(jù)。
  • -getBytes:
  • -getBytes:length:
  • -getBytes:range:

接收數(shù)據(jù),復(fù)制所給范圍內(nèi)字節(jié)到一個(gè)給定的緩沖區(qū)中。

  • -subdataWithRange:

    返回包含在給定范圍內(nèi)的數(shù)據(jù)對象。

  • -rangeOfData:options:range:

在給定的范圍內(nèi),以給定的選項(xiàng),查找并返回給定數(shù)據(jù)的第一個(gè)發(fā)生的范圍。

3. Base-64 Encoding

填坑...

Testing Data

  • -isEqualToData:
    對比data

*##### length
屬性,data的數(shù)量

4. Storing Data

  • -writeToFile:atomically:

將接收到的字節(jié)寫入給定路徑指定的文件。
atomically這個(gè)參數(shù)意思是,如果為YES則保證文件的寫入原子性,就是說會先創(chuàng)建一個(gè)臨時(shí)文件,直到文件內(nèi)容寫入成功再導(dǎo)入到目標(biāo)文件里。 如果為NO,則直接寫入目標(biāo)文件里。

  • -writeToFile:options:error:
typedef NS_OPTIONS(NSUInteger, NSDataWritingOptions) {
    //等同于上面的atomically == YES
    NSDataWritingAtomic = 1UL << 0, 
    //如果已存在文件,則不會覆蓋原文件,寫入失敗。
    NSDataWritingWithoutOverwriting NS_ENUM_AVAILABLE(10_8, 6_0) = 1UL << 1, 
    //資源沒有與其相關(guān)聯(lián)的特殊保護(hù)。任何時(shí)候都可以讀取或?qū)懭胭Y源
    NSDataWritingFileProtectionNone NS_ENUM_AVAILABLE_IOS(4_0)                                  = 0x10000000,
    //資源會以加密格式儲存在磁碟,當(dāng)裝置處於鎖定狀態(tài)或者正在開機(jī)時(shí),將無法進(jìn)行讀取或?qū)懭搿?    NSDataWritingFileProtectionComplete NS_ENUM_AVAILABLE_IOS(4_0)                              = 0x20000000,
    //資源會以加密格式儲存在磁碟。當(dāng)裝置處於鎖定狀態(tài)時(shí),可以建立資源,但是一旦關(guān)閉資源,就無法再次開啟,直到裝置解除鎖定。如果在解除鎖定時(shí)開啟了資源,則可以如常繼續(xù)存取資源,即使使用者鎖定了裝置也無妨。
    NSDataWritingFileProtectionCompleteUnlessOpen NS_ENUM_AVAILABLE_IOS(5_0)                    = 0x30000000,
    //資源會以加密格式儲存在磁碟,只有在裝置開機(jī)之後,才能存取資源。在使用者首次解除鎖定裝置之後,您的應(yīng)用程式可以存取資源,即使使用者之後鎖定了裝置,還是可以繼續(xù)存取。
    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:

填坑...

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容