我正在從緩存的序列化解碼自定義對象。我已經對該對象進行了版本化,因爲它是編碼的,而且如果序列化版本是舊版本,我想將其丟棄。我的印象是,我可以從我的initWithCoder:方法返回零,一切都會好起來的。這是拋出一個錯誤。當從NSCoder解碼對象時,最佳的中止方法是什麼?
編輯 - 每NSObject中的+版本:文件「版本號適用於NSArchiver/NSUnarchiver,但不是的NSKeyedArchiver/NSKeyedUnarchiver一個密鑰歸檔不編碼類的版本號。」。我正在使用密鑰存檔器,因此這種方法無濟於事。
我用我自己的嵌入式版本號,而不是NSObject的版本+ NSCoder的versionForClassName :.這是否是這樣的呢?如果Class版本不匹配,NSCoder會自動放棄嘗試解碼,或者我需要手動執行此檢查。
目前我在做這個:
- (id)initWithCoder:(NSCoder *)coder {
if (![coder containsValueForKey:@"Class.User.version"]) {
// Version information missing
self = nil;
return nil;
}
NSInteger modelVersion = [coder decodeIntForKey:@"Class.User.version"];
if (modelVersion < USER_MODEL_VERSION) {
// Old user model, discard
self = nil;
return nil;
}
...
}
,當它試圖解碼舊版本
-[__NSPlaceholderDictionary initWithObjects:forKeys:]: number of objects (0) not equal to number of keys (46)'
這一切似乎奇怪,因爲初始化失敗有任何我得到這個錯誤原因的數量,並且該模式是在這種情況下返回零,所以這應該真的崩潰解碼器?
編輯 - 根據Apple's documentation這聽起來像我正在接近這個正確的方式。然而,似乎並沒有一種機制可以在對象舊且過時的情況下完全中止解碼。我沒有或不想從舊對象獲得升級路徑,那麼我該怎麼做?
是啊,這件事情可以做,但它結束了,要求我做兩遍解碼。一次解碼並再次刪除任何零或設置了特殊標誌的對象。我看到的更大的問題是,init方法返回nil是完全合法的,除了這個之外,它們可能會出於各種原因這樣做。從init中返回nil使解碼器崩潰的事實對我來說似乎是一個錯誤。無論如何,聽起來這可能是一個錯誤,所以我將在此期間接受這個功能解決方案。 – DougW
您正在將Apple的文檔解釋爲「不解碼舊的,過時的值」。它的實際含義是「不要編碼舊的,過時的值,那麼你不必解碼它們」。因此解碼一次,然後不要在最後寫入它們。 – Greg