2011-07-09 35 views
4

我正在從緩存的序列化解碼自定義對象。我已經對該對象進行了版本化,因爲它是編碼的,而且如果序列化版本是舊版本,我想將其丟棄。我的印象是,我可以從我的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這聽起來像我正在接近這個正確的方式。然而,似乎並沒有一種機制可以在對象舊且過時的情況下完全中止解碼。我沒有或不想從舊對象獲得升級路徑,那麼我該怎麼做?

回答

1

而不是將self設置爲nil,將您解碼的所有單個屬性設置爲nil,然後返回self。所以,這樣寫:

if (modelVersion < USER_MODEL_VERSION) { 
    // Old user model, discard 
    object1 = nil; 
    object2 = nil; 
    ... 
    object46 = nil; 
} 
return self; 

這將從根本上返回正確的類型和所有的對象,但所有的屬性將是nil

+0

是啊,這件事情可以做,但它結束了,要求我做兩遍解碼。一次解碼並再次刪除任何零或設置了特殊標誌的對象。我看到的更大的問題是,init方法返回nil是完全合法的,除了這個之外,它們可能會出於各種原因這樣做。從init中返回nil使解碼器崩潰的事實對我來說似乎是一個錯誤。無論如何,聽起來這可能是一個錯誤,所以我將在此期間接受這個功能解決方案。 – DougW

+0

您正在將Apple的文檔解釋爲「不解碼舊的,過時的值」。它的實際含義是「不要編碼舊的,過時的值,那麼你不必解碼它們」。因此解碼一次,然後不要在最後寫入它們。 – Greg

相關問題