2016-04-22 3 views
2

У меня есть [Int:Bool] словаря и я пытаюсь сохранить его в мою NSDictionary .. Тем не менее, он выходит из строя с ошибкой Attempt to set a non-property-list objectСохранение и загрузка пользовательского словарь - NSUserDefaults

let dictionary = [Int:Bool]() 


self.dictionary[2] = true 
self.dictionary[3] = false 

NSUserDefaults.standardUserDefaults().setObject(dictionary, forKey: "dictionary") 

Кроме того, для загрузки, первого Я пробовал это, но ошибка, зарегистрированная в нем, строго требует AnyObject ?.

NSUserDefaults.standardUserDefaults().objectForKey("dictionary") 

Тогда я попробовал это и вошли:

NSUserDefaults.standardUserDefaults().objectForKey("dictionary") as? [Int:Bool] 

Я также попытался dictionaryForKey. Я получил ..

NSUserDefaults.standardUserDefaults().dictionaryForKey("dictionary") 

Невозможно присвоить значение типа [String: AnyObject], чтобы ввести [Int: Bool]


Итак, какой из этих 2 является лучшим подходом к брать? (Значения будут факультативными в моем случае, я думаю)

1. 
NSUserDefaults.standardUserDefaults().objectForKey("dictionary") as? [Int:Bool] ?? [Int:Bool]() 

2. 
NSUserDefaults.standardUserDefaults().objectForKey("dictionary") as? [Int:Bool])! 
+0

Вы синхронизированы ваши NSUserDefaults после сохранения? 'NSUserDefaults.standardUserDefaults(). Synchronize()' –

+0

Я думаю, вы должны использовать 'dictionaryForKey (_ :)'. –

+0

Ahh. Я полностью забыл добавить его к вопросу. Я также попробовал это. Получение ошибки .. Обновлен мой вопрос – senty

ответ

7

Swift 4

компании основных типов, UserDefaults может сохранить любой объект, который соответствует Codable протоколу. Dictionary является одним из типов, реализующих этот протокол. Вам даже не нужно писать собственный код:

let dictionary = ["name": "Adam"] 

// Save to User Defaults 
UserDefaults.standard.set(dictionary, forKey: "names") 

// Read from User Defaults  
let saved = UserDefaults.standard.value(forKey: "names") as? [String: String] 

Посмотреть подробнее о Codable

Swift 3

Вы можете использовать UserDefaults сохранить Dictionary до тех пор, как ключ и значение типы типы, которые могут быть представлены в формате plist (NSNumber, Data и т. д.). Если это не так, мы всегда можем сериализовать другие типы до Data при записи и десериализации от Data при чтении.Это может быть достигнуто с довольно простым расширением UserDefaults использованием NSKeyArchiver:

extension UserDefaults { 
    /// Save dictionary on key 
    open func set<Key, Value>(dictionary: [Key: Value]?, forKey key: String) { 
     let data = NSKeyedArchiver.archivedData(withRootObject: dictionary as Any) 
     set(data, forKey: key) 
    } 

    // Retrieve dictionary for key 
    open func dictionary<Key, Value>(forKey key: String) -> [Key: Value]? { 
     guard let data = object(forKey: key) as? Data else { return nil } 
     return NSKeyedUnarchiver.unarchiveObject(with: data) as? [Key: Value] 
    } 
} 

Теперь вы можете вызывать эти методы:

let ages = ["Adam": 25] 

// Save 
UserDefaults.standard.set(dictionary: ages, forKey: "ages") 

// Read 
let saved: [String: Int]? = UserDefaults.standard.dictionary(forKey: "ages") 
print(saved) // Optional(["Adam": 25]) 

Swift 2

Сохранить пользовательские данные

func setCustomDictionary(dict: [Int: Bool]) { 
    let keyedArch = NSKeyedArchiver.archivedDataWithRootObject(dict) 

    NSUserDefaults.standardUserDefaults().setObject(keyedArch, forKey: "dictionary") 
} 

Получить данные

func getDictionary() -> [Int: Bool]? { 
    let data = NSUserDefaults.standardUserDefaults().objectForKey("dict") 
    let object = NSKeyedUnarchiver.unarchiveObjectWithData(data as! NSData) 
    return object as? [Int: Bool] 
} 

Использование

var customDictionary = [Int: Bool]() 
customDictionary[2] = true 
customDictionary[3] = false 

// Store data in NSUserDefaults 
setCustomDictionary(customDictionary) 

// Get data from NSUserDefaults 
let userDefaultsDictionary = getDictionary() 
+1

Не что-то типа '[Int: Bool]' автоматически заносится в 'NSDictionary'? –

+0

Нет. Это потому, что словарь Swift является общей структурой 'Dictionary ' while 'NSDictionary' является классом ObjectiveC' NSObject'. Они были соединены в более ранних версиях Свифта, но теперь их нет. –

+0

Можете ли вы вернуть это с помощью источника? Это работает для меня на детской площадке: 'let dictionary: NSDictionary = [1:" a ", 2:" b "]'. –

0

У меня была аналогичная проблема, но с различными типами данных. Мое предложение заключается в преобразовании в NSData и извлекать данные, как так:

/// Save 
NSUserDefaults.standardUserDefaults().setObject(NSKeyedArchiver.archivedDataWithRootObject(object), forKey: key) 

/// Read 
var data = NSUserDefaults.standardUserDefaults().objectForKey(key) as NSData 
var object = NSKeyedUnarchiver.unarchiveObjectWithData(data) as [String: String] 

(Хотя это упоминается [String: String] Я на самом деле используется для [[String: AnyObject]] и работала, так что, возможно, это может работать для вас тоже)

0

Это для Swift 3

func setCustomDictionary(dict: [Int: Bool]) { 
    let keyedArch = NSKeyedArchiver.archivedData(withRootObject: dict) 

    UserDefaults.standard.set(keyedArch, forKey: "dictionary") 
} 

func getDictionary() -> [Int: Bool]? { 
    let data = UserDefaults.standard.object(forKey: "dict") 
    let object = NSKeyedUnarchiver.unarchiveObject(with: (data as! NSData) as Data) 
    return object as? [Int: Bool] 
} 
0

если вы больше типов нужду вы можете использовать дженерики, как это:

func saveUserDefaults<T>(withKey key: String, dict: AnyObject, myType: T.Type) { 
    guard let dict = dict as? T else { 
     print("Type mismatch") 
     return 
    } 
    let archiver = NSKeyedArchiver.archivedData(withRootObject: dict) 
    UserDefaults.standard.set(archiver, forKey: key) 
} 

func getUserDefaults<T>(withKey key: String, myType: T.Type) -> T? { 
    let unarchivedObject = getUserDefaultData(withKey: key) 
    return unarchivedObject as? T 
} 

func getUserDefaultData(withKey key: String) -> Any? { 
    guard let data = UserDefaults.standard.object(forKey: key) else { 
     return nil 
    } 
    guard let retrievedData = data as? Data else { 
     return nil 
    } 
    return NSKeyedUnarchiver.unarchiveObject(with: retrievedData) 
} 

Например [Int: Int] Тип использования:

var customDictionary = [Int: Int]() 
    customDictionary[234] = 1 
    customDictionary[24] = 2 
    customDictionary[345] = 3 

    saveUserDefaults(withKey: "hello", dict: customDictionary as AnyObject, myType: [Int: Int].self) 
    let savedDictionary = getUserDefaults(withKey: "hello", myType: [Int: Int].self) 
    print(savedDictionary) 
Смежные вопросы