作者兩年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é):
- 如果通過方法
dataWithBytes:length:創(chuàng)建data時(shí),length的大小小于實(shí)際內(nèi)容大小時(shí),會創(chuàng)建一個(gè)byte為0的data對象。通過data轉(zhuǎn)string,輸出為空。 - 如果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對象。

`
兩個(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:
填坑...