як швидко зберегти та прочитати масив масиву в NSUserdefaults?


81

Мені потрібно створити масив, щоб додати об’єкти з таким форматом, як словник у Swift: ["key1": "value1", "key2": "value2"]

Коли я намагаюся зберегти його з NSUserDefaultsусіма, це правильно, але при зчитуванні NSUserDefaultsза допомогою ключа це виходить з ладу. Який тип даних потрібен моєму var obj?

let def = NSUserDefaults.standardUserDefaults()
var key = "keySave"
var element: AnyObject!

var array1: [AnyObject!] = []
array1.append(["key1": "val1", "key2": "val2"])
array1.append(["key1": "val1", "key2": "val2"])

//save
var savestring : [AnyObject!]
savestring = array1
var defaults = NSUserDefaults.standardUserDefaults()
defaults.setObject(savestring, forKey: key)
defaults.synchronize()

//read
var obj: [AnyObject!] = []
if(obj != nil){
    print("size: ")
    print(obj.count) //vary long value confused..
    element = obj[0]  //crash
    print(element.objectForKey("key1"))
}

3
Схоже, NSUserDefaults може обробляти String, але не Array і Dictionary, працюючи лише для типів NS *, що описують документи. Отже, це схоже на помилку в Swift.
zaph

Щоб трохи вийти за межі того, що говорить @Zaph, я тестував за допомогою [String], і він не працює, але працює з [NSString]. Перевірте мою відповідь.
HpTerm

Відповіді:


215

Питання звучить "масив масиву", але я думаю, що більшість людей, ймовірно, приходять сюди, просто бажаючи знати, як зберегти масив UserDefaults. Для цих людей я додам кілька типових прикладів.

Рядковий масив

Зберегти масив

let array = ["horse", "cow", "camel", "sheep", "goat"]

let defaults = UserDefaults.standard
defaults.set(array, forKey: "SavedStringArray")

Отримати масив

let defaults = UserDefaults.standard
let myarray = defaults.stringArray(forKey: "SavedStringArray") ?? [String]()

Int масив

Зберегти масив

let array = [15, 33, 36, 723, 77, 4]

let defaults = UserDefaults.standard
defaults.set(array, forKey: "SavedIntArray")

Отримати масив

let defaults = UserDefaults.standard
let array = defaults.array(forKey: "SavedIntArray")  as? [Int] ?? [Int]()

Булівський масив

Зберегти масив

let array = [true, true, false, true, false]

let defaults = UserDefaults.standard
defaults.set(array, forKey: "SavedBoolArray")

Отримати масив

let defaults = UserDefaults.standard
let array = defaults.array(forKey: "SavedBoolArray")  as? [Bool] ?? [Bool]()

Масив дати

Зберегти масив

let array = [Date(), Date(), Date(), Date()]

let defaults = UserDefaults.standard
defaults.set(array, forKey: "SavedDateArray")

Отримати масив

let defaults = UserDefaults.standard
let array = defaults.array(forKey: "SavedDateArray")  as? [Date] ?? [Date]()

Об’єктний масив

Спеціальні об’єкти (і, отже, масиви об’єктів) потребують трохи більше роботи, щоб зберегти їх UserDefaults. Дивіться наступні посилання, щоб дізнатися, як це зробити.

Примітки

  • Оператор злиття nil ( ??) дозволяє повернути збережений масив або порожній масив без збоїв. Це означає, що якщо об’єкт повертає нуль, тоді ??замість нього буде використано значення, яке слідує за оператором.
  • Як ви можете бачити, основна установка була однакова для Int, Boolі Date. Я також тестував це за допомогою Double. Наскільки мені відомо, все, що ви можете зберегти у списку властивостей, буде працювати так.

16

Просто щоб додати те, що говорить @Zaph у коментарях.

У мене така ж проблема, як і у вас, як відомо, масив Stringне збережено. Незважаючи на те, що Apple мостує такі типи, як String та NSString, я не зміг зберегти масив [String]жодного з них [AnyObject].

Однак безліч [NSString]робіт працює для мене.

Отже, ваш код може виглядати так:

var key = "keySave"

var array1: [NSString] = [NSString]()
array1.append("value 1")
array1.append("value 2")

//save
var defaults = NSUserDefaults.standardUserDefaults()
defaults.setObject(array1, forKey: key)
defaults.synchronize()

//read
if let testArray : AnyObject? = defaults.objectForKey(key) {
    var readArray : [NSString] = testArray! as [NSString]
}

Зверніть увагу, що я створив масив NSString, а не словник. Я не перевіряв, чи працює це зі словником, але, мабуть, вам доведеться визначити речі, [NSString : NSString]щоб він працював.

РЕДАГУВАТИ

Перечитавши своє питання та заголовок, про який ви говорите array of array. Я думаю, що поки ти залишишся NSString, масив масиву буде працювати. Однак, якщо ви вважаєте, що моя відповідь неактуальна, просто повідомте мене в коментарях, і я її видалю.


11

Ось приклад читання та запису списку об’єктів типу, SNStockякий реалізується NSCoding- ми маємо доступ до всього списку watchlist, та два методи додавання та видалення об’єктів, тобто addStock(stock: SNStock)та removeStock(stock: SNStock).

import Foundation

class DWWatchlistController {

  private let kNSUserDefaultsWatchlistKey: String = "dw_watchlist_key"

  private let userDefaults: NSUserDefaults

  private(set) var watchlist:[SNStock] {

    get {
      if let watchlistData : AnyObject = userDefaults.objectForKey(kNSUserDefaultsWatchlistKey) {
        if let watchlist : AnyObject = NSKeyedUnarchiver.unarchiveObjectWithData(watchlistData as! NSData) {
          return watchlist as! [SNStock]
        }
      }
      return []
    }

    set(watchlist) {
      let watchlistData = NSKeyedArchiver.archivedDataWithRootObject(watchlist)
      userDefaults.setObject(watchlistData, forKey: kNSUserDefaultsWatchlistKey)
      userDefaults.synchronize()
    }
  }

  init() {
    userDefaults = NSUserDefaults.standardUserDefaults()
  }

  func addStock(stock: SNStock) {
    var watchlist = self.watchlist
    watchlist.append(stock)
    self.watchlist = watchlist
  }

  func removeStock(stock: SNStock) {
    var watchlist = self.watchlist
    if let index = find(watchlist, stock) {
      watchlist.removeAtIndex(index)
      self.watchlist = watchlist
    }
  }

}

Пам'ятайте, що ваш об'єкт повинен реалізувати,NSCoding інакше кодування не буде працювати. Ось як SNStockвиглядає:

import Foundation

class SNStock: NSObject, NSCoding
{
  let ticker: NSString
  let name: NSString

  init(ticker: NSString, name: NSString)
  {
    self.ticker = ticker
    self.name = name
  }

  //MARK: NSCoding

  required init(coder aDecoder: NSCoder) {
    self.ticker = aDecoder.decodeObjectForKey("ticker") as! NSString
    self.name = aDecoder.decodeObjectForKey("name") as! NSString
  }

  func encodeWithCoder(aCoder: NSCoder) {
    aCoder.encodeObject(ticker, forKey: "ticker")
    aCoder.encodeObject(name, forKey: "name")
  }

  //MARK: NSObjectProtocol

  override func isEqual(object: AnyObject?) -> Bool {
    if let object = object as? SNStock {
      return self.ticker == object.ticker &&
        self.name == object.name
    } else {
      return false
    }
  }

  override var hash: Int {
    return ticker.hashValue
  }
}

Сподіваюся, це допомагає!


3

Спробуйте це.

Щоб отримати дані з UserDefaults.

var defaults = NSUserDefaults.standardUserDefaults()
var dict : NSDictionary = ["key":"value"]
var array1: NSArray = dict.allValues // Create a dictionary and assign that to this array
defaults.setObject(array1, forkey : "MyKey")

var myarray : NSArray = defaults.objectForKey("MyKey") as NSArray
println(myarray)

Я додаю var dict: [AnyObject!] = [] Та var array1: NSArray = dict, але це порожньо, як це зробити правильно?
user3745888 07

@AlvinVarghese Насправді спробуйте код. Існує помилка, і навіть коли це виправлено, єдиним збереженим є масив з одним записом: "value".
zaph

3

Свіфт 4.0

Магазин:

let arrayFruit = ["Apple","Banana","Orange","Grapes","Watermelon"]    

 //store in user default
 UserDefaults.standard.set(arrayFruit, forKey: "arrayFruit")

Отримати:

if let arr = UserDefaults.standard.array(forKey: "arrayFruit") as? [String]{
        print(arr)
    }

1

Ось:

var array : [String] = ["One", "Two", "Three"]
let userDefault = UserDefaults.standard
// set
userDefault.set(array, forKey: "array")
// retrieve 
if let fetchArray = userDefault.array(forKey: "array") as? [String] {
    // code 
}

0

Якщо ви працюєте з Swift 5+, вам доведеться скористатися UserDefaults.standard.setValue(value, forKey: key)і, щоб отримати збережені дані, ви повинні використовувати UserDefaults.standard.dictionary(forKey: key).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.