【问题标题】:NSUserDefaults Loading IssueNSUserDefaults 加载问题
【发布时间】:2016-07-05 00:26:11
【问题描述】:

每当我打开我的应用程序时,它都不会加载我的数组值,因为没有调用 != nil 函数。对此我有什么办法吗?

代码:

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

    var toDoData = NSUserDefaults.standardUserDefaults()
    if (toDoData.valueForKey("TDDATA") != nil){
    todos = toDoData.valueForKey("TDDATA") as! NSArray as! [TodoModel]
   }

    if todos.count != 0{
    toDoData.setValue(todos, forKeyPath: "TDDATA")
    toDoData.synchronize()
    }
}

不用担心桌子。它完美地填充。我只需要修复加载数据问题。

您的答案中包含的代码很有帮助!

谢谢。

更新:

这是 TodoModel:

import Foundation
import UIKit


class TodoModel : NSObject, NSCoding {
var id: String
var image: String
var title: String
var desc: String
var scores: String


init (id: String, image: String, title: String, desc: String, scores: String) {
    self.id = id
    self.image = image
    self.title = title
    self.desc = desc
    self.scores = scores

  }

}

【问题讨论】:

  • 你还把什么东西保存到NSUserDefaults?此保存不会执行,因为计数将为 0
  • 我知道。我只需要一种在没有数据加载时应用程序不会崩溃的执行方法。
  • 您显示的代码(可能)没问题,但是当您向todos 数组添加新条目时,您需要将数据保存在某处。我说可能是因为我不知道你是否为ToDoModel 实现了 NSCoding。您应该在第一个 if 之后有一个 else,它将一个空数组分配给 todos
  • @AndyLebo 从设备中删除应用程序并再次调试。当你第二次重新启动应用程序时,显然你会有一些缓存,它会再次击中你的 != 0 设置器。也检查一下逻辑。

标签: ios xcode swift nsarray nsuserdefaults


【解决方案1】:

valueForKeysetValue:forKeyPath 是 KVC(键值编码)方法(阅读 herehere)。它不会帮助您读取/写入用户默认数据库。

查看NSUserDefaultsdocumentation,有许多方法可用于获取和设置默认数据库中的值。由于您使用的是数组,我们将使用:

  • arrayForKey 获取。
  • setObject:forKey 设置。 (没有特定于数组的设置器)

编辑:在您的viewDidAppear 中试试这个。在这里,我们检查是否有数据,如果有,我们将其存储。如果我们没有数据,则检查默认数据库是否保存了一些数据。如果是这样,请改用它。最好只从viewDidLoad 中的默认数据库加载数据,然后保存在viewDidAppear 中,或者更好的是,添加待办事项时调用的函数。

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

    let defaults = NSUserDefaults.standardUserDefaults()
    if todos.count > 0 {
        // Save what we have
        let data = NSKeyedArchiver.archivedDataWithRootObject(todos)
        defaults.setObject(data, forKey: "TDDATA")
        defaults.synchronize()
        print("saved \(todos.count)")
    } else if let storedTodoData = defaults.dataForKey("TDDATA"),
        storedTodos = NSKeyedUnarchiver.unarchiveObjectWithData(storedTodoData) as? [TodoModel] {
        // There was stored data! Use it!
        todos = storedTodos
        print("Used \(todos.count) stored todos")
    }
}

此外,我们必须在您的模型中实现NSCoding 协议。这应该是这样的:

class TodoModel: NSObject, NSCoding {
    var myInt: Int = 0
    var myString: String?
    var myArray: [String]?

    required init?(coder aDecoder: NSCoder) {
        myInt = aDecoder.decodeIntegerForKey("myInt")
        myString = aDecoder.decodeObjectForKey("myString") as? String
        myArray = aDecoder.decodeObjectForKey("myArray") as? [String]
    }

    func encodeWithCoder(aCoder: NSCoder) {
        aCoder.encodeInteger(myInt, forKey: "myInt")
        aCoder.encodeObject(myString, forKey: "myString")
        aCoder.encodeObject(myArray, forKey: "myArray")
    }
}

(当然,用您的模型可能具有的任何属性替换 myInt、myString、myArray 等。)

【讨论】:

  • 另外,您确实没有任何理由立即将待办事项保存到默认数据库。保存待办事项后这样做会更有意义。
  • 所以我将代码移至 viewDidAppear。此外,每当我在 todos 中添加一个元素时,我都会返回此页面并返回此代码。现在的问题是,当我向数组添加一个元素时,它会返回此页面并显示新的 tableViewCell,但是一旦它运行 viewDid Appear 代码,它就会消失。可能是因为它在保存数组之前加载了空数组。我知道这是一个问题,但我仍然不确定如何解决它(我使用了你的代码)。请帮忙?谢谢
  • 总而言之,我需要一种方法来定义 toDoData 与“TDDATA”一起使用而不创建操作,我不知道该怎么做。请帮助@Santa_Claus
  • @AndyLebo 检查我更新的答案。如果您有任何问题,请告诉我。
  • @Santa_Claus 我运行了您更新的代码并收到了 SIGABRT 错误。我打赌这是因为当 todos == 0 时没有创建数据库。这是错误消息:由于未捕获的异常 'NSInvalidArgumentException' 导致应用程序终止,原因:'尝试插入非属性列表对象(“" ) 用于密钥 TDDATA'
猜你喜欢
  • 1970-01-01
  • 2011-08-08
  • 2016-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-13
相关资源
最近更新 更多