要儲存 Objective-C 的物件,該物件就得實作 NSCoding 協定 (protocol) 。所謂的協定是一個共通的程式規格,凡是協定宣告的方法都需要實作出來,也就是要自己定義方法內容。
由於我們要儲存的是 Encrypt 型態 (type) 的屬性 encrypt ,因此 Encrypt 要先實作 NSCoding ,實作寫法如下
@interface Encrypt: NSObject <NSCoding>
也就是在 @interface 那一行,寫在所繼承的物件之後,我們需要修改 Encrypt.h 中的這一行。
NSCoding 需要實作兩個方法,分別是 encodeWithCoder: 與 initWithCoder:
- (void) encodeWithCoder: (NSCoder *) encoder { [encoder encodeObject: cArray forKey: @"cArray"]; } - (id) initWithCoder: (NSCoder *) decoder { cArray = [decoder decodeObjectForKey: @"cArray"]; return self; }
這裡我們只儲存 Encrypt 型態的 cArray 屬性,因為 cArray 為密碼表,儲存密碼表就可以了。存檔是用 encodeWithCoder: 方法,藉由 NSCoder 型態參數 (parameter) encoder 的 encodeObject:forKey: 方法,以 cArray 作為第一個參數,第二個參數為 key 值,我們這裡用 @"cArray" ,讀檔(載入檔案)則是用 decodeObjectForKey: 方法,提供 key 值當參數,然後將回傳值指派回 cArray 。
我們需要把以上的 encodeWithCoder: 與 initWithCoder: 放入 Encrypt.m 之中,至於標頭檔 Encrypt.h 無須加入 encodeWithCoder: 與 initWithCoder: 的宣告,因為這兩個方法已經宣告在 NSCoding 之中,而 Encrypt 也已實作 NSCoding 了。
現在回到 EncryptController , Encrypt 型態的屬性 encrypt 已經可以被存檔了,我們要來設計 loadEncrypt: 與 saveEncrypt: 。這裡要先講一個觀念。
許多物件導向程式語言 (object-oriented programming language) 遇到無法預期的狀況,就像我們要開啟或儲存指定檔名的檔案,為了預防檔案不存在導致程式發生錯誤,因此這些物件導向程式語言大都提供例外處理 (exception handling) 的機制,檔案不存在的話就發起例外 (exception) 。 Objective-C 的例外處理則是利用 @try 、 @catch 、 @finally 三個指令。
程式中一碰到 @try 的時候,會先執行 @try 的部份看能否順利執行,如果例外發生就跳到 @catch 的地方, @finally 可有可無,因為這是一定會執行的部份。不過例外處理最大的缺點是浪費太多系統資源,降低程式的執行效率,因此 Objective-C 的原則是能不 @try 就不 @try 囉!
我們提供的 loadEncrypt: 與 saveEncrypt: 並不包含 @try 的部份,如下
- (IBAction) loadEncrypt: (id)sender { BOOL isFileExist = [[NSFileManager defaultManager] fileExistsAtPath: @"../../encryptor"]; if (isFileExist) { encrypt = [NSKeyedUnarchiver unarchiveObjectWithFile: @"../../encryptor"]; [displayField setStringValue: @"This is Load button. Encrypt object is loaded."]; } else { [displayField setStringValue: @"This is Load button. Encrypt object is not loaded."]; } } - (IBAction) saveEncrypt: (id)sender { BOOL succeed = [NSKeyedArchiver archiveRootObject: encrypt toFile: @"../../encryptor"]; if (!succeed){ [displayField setStringValue: @"This is Save button. Encrypt object is not saved."]; } else { [displayField setStringValue: @"This is Save button. Encrypt object is saved."]; } }
讀檔 loadEncrypt: 是利用 NSFileManager 的 defaultManager ,然後以 fileExistsAtPath: 測試指定路徑 "../../encryptor" 是否存在, encryptor 就是下面 saveEncrypt: 存檔的指定檔名,這樣回傳 YES 或 NO 。 NO 的話就不會進行開啟檔案的動作, YES 的話就利用 NSKeyedUnarchiver 的 unarchiveObjectWithFile: 開啟指定路徑,然後將結果指派給 encrypt 。
存檔 saveEncrypt: 則是直接利用 NSKeyedArchiver 的 archiveRootObject:toFile: 儲存 encrypt 到指定路徑 "../../encryptor" 囉!
好了,這樣就有存檔與讀檔的功能了。我們也已經完成 EncryptController.m ,發展這個編碼與解碼的軟體也告一段落了,下一步是什麼呢?
中英文術語對照 | |
---|---|
物件 | object |
屬性 | property |
方法 | method |
協定 | protocol |
型態 | type |
參數 | parameter |
物件導向程式語言 | object-oriented programming language |
例外處理 | exception handling |
例外 | exception |
您可以繼續參考
GUI 篇
相關目錄
Objective-C 入門指南
Objective-C 教材
首頁
參考資料
Learning Objective-C: A Primer
The Objective-C Programming Language
Cocoa Fundamentals Guide
Coding Guidelines for Cocoa
Advanced Memory Management Programming Guide
Archives and Serializations Programming Guide
沒有留言:
張貼留言