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, но я получите ошибку, которую Im не смог решить, как показано ниже:

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

+0

Как насчет использования NSDictionary вместо массива? NSDictionary затем может быть сохранен с помощью NSUserDefaults. – David

+1

Возможно, вы также захотите включить именно то, как вы пытались это решение. –

ответ

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

это не скомпилировано с быстрым, вам нужно удалить автоматическое развернутое объявление параметров NSCoding. –

+0

Исправлено. Простите, не тестировал код, который работал в предыдущих бета-версиях Xcode 6. – Kirsteins

+0

Я тоже это пробовал. У меня было много проблем с вызовом пользовательского инициализатора (со значениями для свойств).Полный код, который я пробовал, но не смог удалить ошибку, был добавлен в главный пост (извините, я не знаю, как правильно отформатировать в комментариях). Было бы здорово, если бы вы могли взглянуть и посмотреть, сможете ли вы разрешить ошибку? – user3535074

6

Основные данные невероятно мощные nd Я настоятельно рекомендую вам попробовать не поколебать его устрашающий внешний вид. Когда ваше приложение вырастет, вы будете невероятно благодарны за то, что вы поддержали свои данные с помощью 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.

В идеале вы не хотите сохранять массивы, потому что тогда вам нужно извлечь весь массив в память, даже если вам нужен один объект.Естественно основные данные будут решать все, что ненужную кучу беспорядок для вас :)

EDIT

Чтобы облегчить себя в Core Data, вы всегда можете посмотреть на Magical Record. Они упрощают большую часть трещины, необходимой для поддержания стека основных данных.

Good Luck

Основные данные Евангелист

+0

Спасибо за ваши комментарии Daniel. Боюсь, что я действительно нашел эту статью и провел несколько часов, пройдя через нее, и пробовал каждый метод, который он объясняет, но в каждой точке есть ошибки, независимо от того, что я делаю. На самом деле я хотел избежать использования основных данных просто потому, что я пытаюсь (но не очень плохо), чтобы ускориться с Swift, и я хотел проверить, что я изучил до сих пор. Может быть, вы правы, может быть, мне нужно просто погрузиться в основные данные ... – user3535074

+0

@ user3535074 подробно расскажите о тех типах ошибок, с которыми вы сталкиваетесь? –

+0

Ive добавил класс в главный пост вместе с ошибкой при попытке сохранить в NSUser defaults.Thanks! – user3535074

 Смежные вопросы

  • Нет связанных вопросов^_^