13

我有一個具有多個屬性的對象數組。這是通過對象的數組循環取一些樣本數據:Swift中的簡單持久存儲器

Name = Rent 
Default Value 750 
This Months Estimate = 750 
Sum Of This Months Actuals = 0 
Risk Factor = 0.0 
Monthly Average = 750.0 
-------------- 
Name = Bills 
Default Value 250 
This Months Estimate = 170 
Sum Of This Months Actuals = 140 
Risk Factor = 0.0 
Monthly Average = 190.0 
-------------- 
Name = Food 
Default Value 240 
This Months Estimate = 200 
Sum Of This Months Actuals = 95 
Risk Factor = 0.0 
Monthly Average = 190.0 
-------------- 
Name = Lunches 
Default Value 100 
This Months Estimate = 150 
Sum Of This Months Actuals = 155 
Risk Factor = 0.899999976158142 
Monthly Average = 190.0 

它的數據非常少,所以我要避免使用核心數據。我需要能夠保存數組,然後再打開它並能夠循環訪問它。我希望使用像NSUserDefaults或NSKeyedArchiver這樣的簡單解決方案,但在Swift中,我無法使用這種類型的數組(我已經在24小時內在線查閱文檔和論壇以及示例...)

你會如何推薦我堅持保存一組像上面那樣的對象?或者可能堅持保存這種類型的數組是不好的做法?

在此先感謝您的幫助!

添加對象類:

class costCategory : NSObject { 
    var name : String 
    var defaultValue : Int 
    var thisMonthsEstimate : Int 
    var sumOfThisMonthsActuals : Int 
    var riskFactor : Float 
    var monthlyAverage : Float 


    init (name:String, defaultValue:Int, thisMonthsEstimate:Int, sumOfThisMonthsActuals:Int, riskFactor:Float, monthlyAverage:Float) { 
     self.name = name 
     self.defaultValue = defaultValue 
     self.thisMonthsEstimate = thisMonthsEstimate 
     self.sumOfThisMonthsActuals = sumOfThisMonthsActuals 
     self.riskFactor = riskFactor 
     self.monthlyAverage = monthlyAverage 
    } 

} 

如果我嘗試保存數組我NSUserDefaults的遇到了錯誤:

Property list invalid for format: 200 (property lists cannot contain objects of type 'CFType') 

我已經使用從NSCoder類繼承,但我試過得到我無法解決的錯誤,如下:

class costCategory : NSObject, NSCoder { 
    var name : String 
    var defaultValue : Int 
    var thisMonthsEstimate : Int 
    var sumOfThisMonthsActuals : Int 
    var riskFactor : Float 
    var monthlyAverage : Float 


    init (name:String, defaultValue:Int, thisMonthsEstimate:Int, sumOfThisMonthsActuals:Int, riskFactor:Float, monthlyAverage:Float) { 
     self.name = name 
     self.defaultValue = defaultValue 
     self.thisMonthsEstimate = thisMonthsEstimate 
     self.sumOfThisMonthsActuals = sumOfThisMonthsActuals 
     self.riskFactor = riskFactor 
     self.monthlyAverage = monthlyAverage 
    } 



    // MARK: NSCoding 

    required convenience init(coder decoder: NSCoder) { 
     self.init() //Error here "missing argument for parameter name in call 
     self.name = decoder.decodeObjectForKey("name") as String 
     self.defaultValue = decoder.decodeIntegerForKey("defaultValue") 
     self.thisMonthsEstimate = decoder.decodeIntegerForKey("thisMonthsEstimate") 
     self.sumOfThisMonthsActuals = decoder.decodeIntegerForKey("sumOfThisMonthsActuals") 
     self.riskFactor = decoder.decodeFloatForKey("riskFactor") 
     self.monthlyAverage = decoder.decodeFloatForKey("monthlyAverage") 

    } 

    func encodeWithCoder(coder: NSCoder) { 
     coder.encodeObject(self.name, forKey: "name") 
     coder.encodeInt(Int32(self.defaultValue), forKey: "defaultValue") 
     coder.encodeInt(Int32(self.thisMonthsEstimate), forKey: "thisMonthsEstimate") 
     coder.encodeInt(Int32(self.sumOfThisMonthsActuals), forKey: "sumOfThisMonthsActuals") 
     coder.encodeFloat(self.riskFactor, forKey: "riskFactor") 
     coder.encodeFloat(self.monthlyAverage, forKey: "monthlyAverage") 

    } 
} 
+0

這是類或值類型? – Kirsteins 2014-10-07 09:48:10

+0

如何使用NSDictionary而不是數組? NSDictionary然後可以使用NSUserDefaults進行存儲。 – David 2014-10-07 09:48:37

+1

您可能還想要包含您嘗試此解決方案的確切方式。 – 2014-10-07 09:51:13

回答

30

一種可能是你的對象屬性轉換:值字符串:對象將它們存儲到NSUserDefaults,然後讓它們和解碼回來。

如果您想使用NSKeyedArchiver存儲您的對象,您的課程需要符合NSCoding並且是NSObject的子類。例如:

class costCategory : NSObject, NSCoding { 
    var name : String 
    var defaultValue : Int 
    var thisMonthsEstimate : Int 
    var sumOfThisMonthsActuals : Int 
    var riskFactor : Float 
    var monthlyAverage : Float 

    init (name:String, defaultValue:Int, thisMonthsEstimate:Int, sumOfThisMonthsActuals:Int, riskFactor:Float, monthlyAverage:Float) { 
     self.name = name 
     self.defaultValue = defaultValue 
     self.thisMonthsEstimate = thisMonthsEstimate 
     self.sumOfThisMonthsActuals = sumOfThisMonthsActuals 
     self.riskFactor = riskFactor 
     self.monthlyAverage = monthlyAverage 
    } 

    // MARK: NSCoding 

    required init(coder decoder: NSCoder) { 
     //Error here "missing argument for parameter name in call 
     self.name = decoder.decodeObjectForKey("name") as String 
     self.defaultValue = decoder.decodeIntegerForKey("defaultValue") 
     self.thisMonthsEstimate = decoder.decodeIntegerForKey("thisMonthsEstimate") 
     self.sumOfThisMonthsActuals = decoder.decodeIntegerForKey("sumOfThisMonthsActuals") 
     self.riskFactor = decoder.decodeFloatForKey("riskFactor") 
     self.monthlyAverage = decoder.decodeFloatForKey("monthlyAverage") 
     super.init() 
    } 

    func encodeWithCoder(coder: NSCoder) { 
     coder.encodeObject(self.name, forKey: "name") 
     coder.encodeInt(Int32(self.defaultValue), forKey: "defaultValue") 
     coder.encodeInt(Int32(self.thisMonthsEstimate), forKey: "thisMonthsEstimate") 
     coder.encodeInt(Int32(self.sumOfThisMonthsActuals), forKey: "sumOfThisMonthsActuals") 
     coder.encodeFloat(self.riskFactor, forKey: "riskFactor") 
     coder.encodeFloat(self.monthlyAverage, forKey: "monthlyAverage") 

    } 
} 

然後你就可以存檔並保存到NSDefaults

let defaults = NSUserDefaults.standardUserDefaults() 
let arrayOfObjectsKey = "arrayOfObjectsKey" 

var arrayOfObjects = [costCategory]() 
var arrayOfObjectsData = NSKeyedArchiver.archivedDataWithRootObject(arrayOfObjects) 

defaults.setObject(arrayOfObjectsData, forKey: arrayOfObjectsKey) 

// ... 

var arrayOfObjectsUnarchivedData = defaults.dataForKey(arrayOfObjectsKey)! 
var arrayOfObjectsUnarchived = NSKeyedUnarchiver.unarchiveObjectWithData(arrayOfObjectsUnarchivedData) as [costCategory] 
+0

這不能用swift編譯,你需要刪除自動解包的NSCoding參數聲明 – 2014-10-07 09:57:01

+0

固定。對不起,沒有測試在以前的Xcode 6測試版中工作的代碼。 – Kirsteins 2014-10-07 10:02:42

+0

我也試過。調用自定義初始化程序(使用屬性的值)時遇到很多問題。我試過的完整代碼,但無法刪除錯誤已添加到主帖子(抱歉,我不知道如何在評論中正確格式)。如果你能看一看,看看你是否能解決這個錯誤,那將是一件好事。 – user3535074 2014-10-07 10:07:33

6

核心數據是令人難以置信的powe而且我強烈建議你儘量不要被其嚇人的外表所左右。當您的應用程序增長時,您會非常感謝您使用Core Data支持您的數據,因爲它的擴展非常好。

這就是說,在NSHipster that covers the basics of using the NSKeyedArchiver上有一篇不錯的文章。所以解決辦法是讓你的對象成爲NSObject的一個子類並且符合NSCoding協議。這使您可以從磁盤上歸檔未歸檔的對象。您可以將您的文件保存到documents directory

那麼你的子類都需要隱解開所有的編碼,能變量,結果將產生:

class costCategory : NSObject, NSCoding { 
var name : String! 
var defaultValue : Int! 
var thisMonthsEstimate : Int! 
var sumOfThisMonthsActuals : Int! 
var riskFactor : Float! 
var monthlyAverage : Float! 


init (name:String, defaultValue:Int, thisMonthsEstimate:Int, sumOfThisMonthsActuals:Int, riskFactor:Float, monthlyAverage:Float) { 
    self.name = name 
    self.defaultValue = defaultValue 
    self.thisMonthsEstimate = thisMonthsEstimate 
    self.sumOfThisMonthsActuals = sumOfThisMonthsActuals 
    self.riskFactor = riskFactor 
    self.monthlyAverage = monthlyAverage 
} 

override init() { 
    super.init() 
} 

// MARK: NSCoding 

required convenience init(coder decoder: NSCoder) { 
    self.init() 
    self.name = decoder.decodeObjectForKey("name") as String 
    self.defaultValue = decoder.decodeIntegerForKey("defaultValue") 
    self.thisMonthsEstimate = decoder.decodeIntegerForKey("thisMonthsEstimate") 
    self.sumOfThisMonthsActuals = decoder.decodeIntegerForKey("sumOfThisMonthsActuals") 
    self.riskFactor = decoder.decodeFloatForKey("riskFactor") 
    self.monthlyAverage = decoder.decodeFloatForKey("monthlyAverage") 
} 

func encodeWithCoder(coder: NSCoder) { 
    coder.encodeObject(self.name, forKey: "name") 
    coder.encodeInteger((self.defaultValue), forKey: "defaultValue") 
    coder.encodeInteger((self.thisMonthsEstimate), forKey: "thisMonthsEstimate") 
    coder.encodeInteger((self.sumOfThisMonthsActuals), forKey: "sumOfThisMonthsActuals") 
    coder.encodeFloat(self.riskFactor, forKey: "riskFactor") 
    coder.encodeFloat(self.monthlyAverage, forKey: "monthlyAverage") 
} 
} 

然後,您可以添加查找位置的方式文檔目錄:

func documentsDirectory() -> NSString { 
    let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) 
    let documentDirectory = paths[0] as String 
    return documentDirectory 
} 

所以歸檔應該是這樣的:

var filePath = documentsDirectory().stringByAppendingPathComponent("fileName") 
NSKeyedArchiver.archiveRootObject(receipts, toFile: filePath) 

,後來你可以從磁盤中讀取您的陣列回:

let receipts = NSKeyedUnarchiver.unarchiveObjectWithFile(filePath) 

我會建議不要使用用戶默認存儲陣列,它的意思商店的喜好,看看這裏的文檔:

The NSUserDefaults class provides a programmatic interface for interacting with the defaults system. The defaults system allows an application to customize its behavior to match a user’s preferences. For example, you can allow users to determine what units of measurement your application displays or how often documents are automatically saved. Applications record such preferences by assigning values to a set of parameters in a user’s defaults database.

理想情況下,您不想保存數組,因爲那樣即使您需要一個對象,您也必須將整個數組提取到內存中。當然核心數據將解決所有的不必要的混亂堆爲你:)

編輯

爲了緩解自己成爲核心數據,你可以經常看Magical Record。它們簡化了維護核心數據堆棧所需的大量工作。

好運

核心數據傳播者

+0

感謝您的意見丹尼爾。我害怕我真的找到了那篇文章,花了幾個小時閱讀並嘗試了它解釋的每種方法,但無論我做什麼,在每一點上都存在錯誤。真的,我想避免使用核心數據,僅僅是因爲我試圖(但很失敗)來加速Swift,我想測試我到目前爲止所研究的內容。也許你是對的,也許我應該只是潛入核心數據...... – user3535074 2014-10-07 09:51:27

+0

@ user3535074請詳細說明你面臨的錯誤類型? – 2014-10-07 09:52:03

+0

當我嘗試保存到NSUser的默認值時,我在主帖子中添加了這個類以及錯誤。謝謝! – user3535074 2014-10-07 10:00:51