ios writeToFile 和 對象序列化


前言:做了一個圖片瀏覽的小demo,支持隨意添加、刪除圖片,圖片放大、縮小,帶矩形框的截圖。隨后幾篇博客都會詳細講解在此過程中遇到的各種問題。這篇主要講,在做添加、刪除這個功能時,遇到的存文件的問題。

我們想實現在以后每次打開這個程序時,不用再一張張手動添加,而會保留用戶上次已經選擇的圖片,那么就需要把這些圖片存入內存,每次從內存中讀取。

正文:

一、存文件有幾種方式?

    直接寫入FILE、對象序列化

 

二、直接寫入FILE

     在我的程序里,我是把圖片都存在一個NSMutableDictionary,每個image都對應一個key。

     1、直接調用NSDictionary的writeToFile:atomically:方法,將dic存入一個指定的目錄。

- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)flagDescription    

 功能:Writes a property list representation of the contents of the dictionary to a given path.

          把一個代表這個dictionary內容的property列表寫入到指定的路徑。

 出現問題:目錄創建沒有問題,但是一直writeToFile寫入失敗??

 分析思路: 查詢方法注釋,有這樣一段話:

This method recursively validates that all the contained objects are property list objects 
(instances of NSData, NSDate, NSNumber, NSString, NSArray, or NSDictionary) before writing out the file,
 and returns NO if all the objects are not property list objects, since the resultant file would not be a valid property list.

這個方法在把dic寫入文件之前,會遞歸的驗證所有包含的對象是否都是property列表里的對象(包括 NSData, NSDate, NSNumber, NSString, NSArray, or NSDictionary)。

如果dic中所有的對象不全是property列表里的對象,那么返回NO,因為最后生成的文件不是一個有效的 property list.

失敗原因:是因為我的dic中存的obj是UIImage,不屬於property list,所以返回失敗。

解決辦法:把UIImage換成property list里的對象NSData,把NSData存入dic中。

NSData *data = UIImagePNGRepresentation(img);  

   

     2、從FILE中取出

     在writeToFile的注釋中,寫到:If the dictionary’s contents are all property list objects, the file written by this method can be used to initialize a new dictionary with the class method dictionaryWithContentsOfFile: or the instance method initWithContentsOfFile:.

   如果這個dic的內容都是property list,那么通過這個方法寫的文件可以用來初始化一個新的dictionary,方法:dictionaryWithContentsOfFile:或者initWithContentsOfFile:.

NSMutableDictionary *dic= [NSMutableDictionary dictionaryWithContentsOfFile:_filePath];

問題:在寫入成功后,我調用這個dictionaryWithContentsOfFile時,得到的新dic總是有問題。

分析原因:寫入問題?參數_filePath問題?寫入如果有問題的話,那么根本就不會成功,換了一個新的path成功了,說明是_filePath的問題。在失敗的打印框中輸入po _filePath,果然是個空指針。這個問題是我怎么都沒有想到的。我把_filePath定為全局變量,在一開始的init方法中,就給它賦了值,可是這里它怎么會是nil了??

      來看一下我的賦值方法:

_filePath = [NSString stringWithFormat:@"%@/Documents/imageViews/test.plist",NSHomeDirectory()];

現在知道問題出在哪了吧?!!在前面的博客中詳細分析過這個問題,凡是沒有用alloc等方法構造的對象,如果在程序的其他地方還要用的話,一定要加上retain!!!
修改后一切ok!

 

三、對象序列化

在接觸新內容時,我們先來回顧一下java的對象序列化。在java中,需要序列化的對象必須實現Serializable接口,通過調用writeObject、readObject這兩個方法存儲、讀取對象。

在oc中,也是類似的。需要序列化的對象必須實現NSCoding協議並重寫encodeWithCoder和initWithCoder兩個方法,分別用以編碼和反編碼,通過調用NSKeyedArchiver、NSKeyedUnarchiver這兩個類來存儲、讀取對象。如果繼承的類已經實現了NSCoding協議,那么子類就不用實現了。

[NSKeyedArchiver archiveRootObject:obj toFile:filename];   //序列化
obj = [NSKeyedUnarchiver unarchiveObjectWithFile: filename];   //反序列化

    因為目前還沒有嘗試,就簡單介紹一下,用到的時候再詳細研究。可參考:http://blog.csdn.net/holydancer/article/details/7371643


四、總結

      1、writeToFile方法,只適用於 NSData, NSDate, NSNumber, NSString, NSArray, or NSDictionary這些類。

      2、我們自定義的類要寫入文件,都是用序列化方法。

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM