【问题标题】:NSUserDefaults not working with UITableView in SwiftNSUserDefaults 在 Swift 中不能与 UITableView 一起使用
【发布时间】:2016-03-10 20:22:51
【问题描述】:

我对 Swift 比较陌生,正在制作一个基本的家庭作业日记应用程序。到目前为止,我所拥有的是嵌入在导航控制器中的 UITableView,该导航控制器嵌入在标签栏控制器中。我已经成功地实现了拉动刷新,在 UIAlertView 中添加数据并在刷新后用这些数据填充表。我需要这个应用程序的持久数据,我听说 NSUserDefaults 是最好的方法,但它对我不起作用。我可以看到它正在添加到 NSUserDefaults,但在我关闭并重新打开应用程序后,它似乎没有重新出现在 UITableView 中。有什么建议?我的代码如下。另外,要将这些数据放到网上,有没有办法将 Google 表格用作我的应用的在线数据库?

import UIKit
var classesData = [String]()
var teachersData = [String]()
let defaults = NSUserDefaults.standardUserDefaults()
var tableData1 = defaults.valueForKey("classesData") as! NSArray
var tableData2 = defaults.valueForKey("teachersData") as! NSArray

class ClassesList: UIViewController, UITableViewDelegate, UITableViewDataSource, UIPopoverPresentationControllerDelegate {
lazy var refreshControl: UIRefreshControl = {
    let refreshControl = UIRefreshControl()
    refreshControl.addTarget(self, action: "handleRefresh:", forControlEvents: UIControlEvents.ValueChanged)

    return refreshControl
}()
@IBOutlet weak var tableView: UITableView!
@IBAction func addClass(sender: AnyObject) {
    var subjectTextField: UITextField?
    var teacherTextField: UITextField?
    let alertController = UIAlertController(title: "Add Class", message: "Please input the name of the subject and the teaceher", preferredStyle: .Alert)
    let done = UIAlertAction(title: "Done", style: .Default, handler: { (action) -> Void in
        classesData.append(subjectTextField!.text!)
        teachersData.append(teacherTextField!.text!)
        print(classesData)
        print(teachersData)
    })
    let cancel = UIAlertAction(title: "Cancel", style: .Cancel) { (action) -> Void in
    }
    alertController.addAction(done)
    alertController.addAction(cancel)
    alertController.addTextFieldWithConfigurationHandler { (textField) -> Void in
        // Enter the textfiled customization code here.
        subjectTextField = textField
        subjectTextField?.placeholder = "Subject"
    }
    alertController.addTextFieldWithConfigurationHandler { (textField) -> Void in
        // Enter the textfiled customization code here.
        teacherTextField = textField
        teacherTextField?.placeholder = "Teacher"
    }
    presentViewController(alertController, animated: true, completion: nil)

}

override func viewDidLoad() {
    super.viewDidLoad()
    self.tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "classCell")
    self.tableView.addSubview(self.refreshControl)


    // Do any additional setup after loading the view, typically from a nib.
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.

}
func handleRefresh(refreshControl: UIRefreshControl) {
    defaults.setValue(classesData, forKey: "classesData")
    defaults.setValue(teachersData, forKey: "teachersData")
    print(tableData1)
    defaults.synchronize()
    self.tableView.reloadData()
    refreshControl.endRefreshing()
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return classesData.count
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("classCell")! as UITableViewCell

    cell.textLabel?.text = (tableData1[indexPath.row] as? String)! + " , " + (tableData2[indexPath.row] as? String)!

    return cell
}

}

【问题讨论】:

  • 您需要检查的第一件事是 NSUserDefaults 是否包含您在打开应用程序时要查找的元素!查看 viewDidLoad 中 NSUserDefaults 的内容,看看它是否包含任何内容!
  • @Gautam Jethwani NSUserDefaults 有一个名为 stringArrayForKey 的方法。你应该看看
  • 如果您说UITableView,我立即怀疑您的数据(无论表中的内容)有点复杂。阅读 Core Data 和数据库结构可能值得您花时间阅读。

标签: ios swift uitableview nsuserdefaults


【解决方案1】:

在启动时,您使用 tableData1 和 tableData2 来存储默认信息,但 classesData 和 teacherData 被初始化为空。当应用程序启动时,它会调用 numberOfRowsInSection 并返回 classesData.count,它是零。您遇到的另一个问题是您的应用程序将在第一次运行时崩溃,因为您使用空的 NSUserDefaults 数据对其进行初始化。重置 iOS 模拟器,然后运行您的应用程序,它会崩溃。您需要检查和处理来自此处介绍的 NSUserDefaults 的空数据:how to save and read array of array in NSUserdefaults in swift?

我建议如下: 1)删除 tableData1 和 tableData1 并在应用程序中的任何地方替换为 classesData 和 teacherData。 2) 创建一个名为 loadUserDefaults() 的新函数,该函数在 viewDidLoad 中调用,该函数在检查空 NSUserDefaults 数据时从 NSUserDefaults 加载数据。 3) 在handleRefresh() 中只保存数据,重新加载表格视图并结束刷新。有了这些建议,工作代码如下。

import UIKit
var classesData = [String]()
var teachersData = [String]()
let defaults = NSUserDefaults.standardUserDefaults()

class ClassesList: UIViewController, UITableViewDelegate, UITableViewDataSource, UIPopoverPresentationControllerDelegate {
    lazy var refreshControl: UIRefreshControl = {
        let refreshControl = UIRefreshControl()
        refreshControl.addTarget(self, action: "handleRefresh:", forControlEvents: UIControlEvents.ValueChanged)

        return refreshControl
    }()
    @IBOutlet weak var tableView: UITableView!
    @IBAction func addClass(sender: AnyObject) {
        var subjectTextField: UITextField?
        var teacherTextField: UITextField?
        let alertController = UIAlertController(title: "Add Class", message: "Please input the name of the subject and the teaceher", preferredStyle: .Alert)
        let done = UIAlertAction(title: "Done", style: .Default, handler: { (action) -> Void in
            classesData.append(subjectTextField!.text!)
            teachersData.append(teacherTextField!.text!)
        })
        let cancel = UIAlertAction(title: "Cancel", style: .Cancel) { (action) -> Void in
        }
        alertController.addAction(done)
        alertController.addAction(cancel)
        alertController.addTextFieldWithConfigurationHandler { (textField) -> Void in
            // Enter the textfiled customization code here.
            subjectTextField = textField
            subjectTextField?.placeholder = "Subject"
        }
        alertController.addTextFieldWithConfigurationHandler { (textField) -> Void in
            // Enter the textfiled customization code here.
            teacherTextField = textField
            teacherTextField?.placeholder = "Teacher"
        }
        presentViewController(alertController, animated: true, completion: nil)

    }

    override func viewDidLoad() {
        super.viewDidLoad()
        self.tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "classCell")
        self.tableView.addSubview(self.refreshControl)
        loadUserDefaults()
    }

    func handleRefresh(refreshControl: UIRefreshControl) {
        defaults.setValue(classesData, forKey: "classesData")
        defaults.setValue(teachersData, forKey: "teachersData")
        defaults.synchronize()
        self.tableView.reloadData()
        refreshControl.endRefreshing()
    }

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return classesData.count
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("classCell")! as UITableViewCell
        cell.textLabel?.text = (classesData[indexPath.row] as? String)! + " , " + (teachersData[indexPath.row] as? String)!

        return cell
    }

    func loadUserDefaults() {
        if let tempClassArray = defaults.valueForKey("classesData") {
            classesData = tempClassArray as! [String]
        }

        if let tempTeacherArray = defaults.valueForKey("classesData") {
            teachersData = tempTeacherArray as! [String]
        }
    }

}

【讨论】:

  • 当您有多个问题时,您应该单独发布,但有关 Google 表格的问题已包含在此帖子中,建议您使用 Google 数据 API:stackoverflow.com/questions/13211682/…
  • 嘿,我会查看 Google 表格链接,但我尝试了您添加的代码,但没有成功。还有其他地方我应该将 valueforkey 放在 viewDidLoad 方法中吗?
  • 如果您想将项目发布为 .zip 文件并提供链接,我可以仔细查看它。我不认为这会是一个问题,因为它似乎是一个课堂作业。您可以通过以下方式做到这一点:meta.stackexchange.com/questions/15821/…
  • Guatam,我已经更新了我上面的答案,因为我已经审查了你的项目。如果这行得通,请投票 +1,如果行不通,请给我另一条评论。
  • 嗨 xdeleon,起初,我尝试实现您提到的更改,但没有成功。然后我复制并粘贴了你的整个代码,它工作了,但它显示了两次主题。我更改了其中一行代码,它起作用了!太感谢了!你是救命稻草,你解决了我几周来一直试图解决的问题。我会尝试找出我的代码和你的代码之间的区别。再次感谢!
猜你喜欢
  • 2011-12-25
  • 1970-01-01
  • 2016-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多