使用带有NSUserDefault的字符串数组的最佳实践

时间:2015-08-12 13:44:00

标签: arrays swift nsuserdefaults optional

我在将一组字符串保存到userDefaults时遇到了一些麻烦。我有一个在类中声明的字符串数组,其属性观察器同步到userDefaults。此外,我希望数组最多限制为5个字符串。

let userDefaults = NSUserDefaults.standardUserDefaults()

var suggestions: [String]! {
    didSet {
        var arrayEnd = suggestions.count
        if arrayEnd >= 5 {
            arrayEnd = 4
        }
        let newArray = Array(suggestions[0...arrayEnd])
        userDefaults.setObject(newArray, forKey: "suggestions")
        userDefaults.synchronize()
    }
}

func getSuggestionData() {
    if userDefaults.valueForKey("suggestions") != nil {
        self.suggestions = userDefaults.valueForKey("suggestions") as? [String]
    }
}

override func viewDidLoad() {
    super.viewDidLoad()

    getSuggestionData()
    suggestions.insert("someString", atIndex: 0)
    }
}

当我运行时,我得到:

  

致命错误:在解包可选值时意外发现nil

在我尝试将新对象插入数组的行上。 我已尝试在此主题中使用该方法,但它没有将任何内容保存到列表中。

我是swift的新手,而且可选类型不是我强大的一面,也许有人知道什么是错的?

2 个答案:

答案 0 :(得分:2)

从用户默认值读取可能返回nil值,使用可选绑定是安全的:

func getSuggestionData() {
  if let suggestionArray = userDefaults.objectForKey("suggestions") {
    self.suggestions = suggestionArray
  } else {
    self.suggestions = [String]()
  }
}

但我建议使用具有已定义默认值的非可选变量。

在应用的AppDelegate中,覆盖init()或插入代码以注册键/值对。

override init()
{
  let defaults = NSUserDefaults.standardUserDefaults()
  let defaultValue = ["suggestions" : [String]()];
  defaults.registerDefaults(defaultValue)
  super.init()
}

注册默认密钥和值是Apple在documentation中建议的方式。

  • 如果尚未写入任何值,则读取默认值(空数组)。
  • 如果有值,则读取实际值

而不是变量suggestions的值观察者实现插入新值的方法,删除最后一个并将数组写入磁盘。 无需使用可选绑定,因为用户默认值中的数组始终具有已定义的状态。

let userDefaults = NSUserDefaults.standardUserDefaults()
var suggestions = [String]()

func insertSuggestion(suggestion : String)
{
  if suggestions.count == 5 { suggestions.removeLast() }
  suggestions.insert(suggestion, atIndex: 0)
  userDefaults.setObject(suggestions, forKey: "suggestions")
  userDefaults.synchronize()
}

func getSuggestionData() {
  suggestions = userDefaults.objectForKey("suggestions") as! [String]
}

override func viewDidLoad() {
  super.viewDidLoad()
  getSuggestionData()
  insertSuggestion("someString")
}

旁注:
如果您不需要明确使用键值编码方法,请不要使用valueForKey:而不是objectForKey:

答案 1 :(得分:0)

嘿,就这样试试吧。

var suggestions: [String] = Array() {

        didSet {
            var arrayEnd = suggestions.count
            if arrayEnd >= 5 {
                arrayEnd = 4
            }
            if arrayEnd > 0
            {
            let newArray = Array(suggestions[0...(arrayEnd-1)])
            userDefaults.setObject(newArray, forKey: "suggestions")
            userDefaults.synchronize()


            }

        }

    }


    func getSuggestionData() {
        if userDefaults.valueForKey("suggestions") != nil {
            self.suggestions = userDefaults.objectForKey("suggestions") as! Array
        }
    }


    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        getSuggestionData()

        if self.suggestions.count > 4
        {
            var str = "\(self.suggestions.count)"
            self.suggestions.insert(str, atIndex: self.suggestions.count)
        }

    }