NSUserDefaults not working with UITableView in Swift

空扰寡人 提交于 2019-12-23 04:54:31

问题


I'm relatively new to Swift and am making a basic homework diary app. What I have so far is a UITableView embedded in a navigation controller which is embedded in a tab bar controller. I have successfully managed to implement a pull to refresh, adding data in a UIAlertView and populating the table with this data after the refresh. I need persistent data for this app and I heard that NSUserDefaults is the best way to do that, but it's not working for me. I can see that it is adding to the NSUserDefaults, but it doesn't seem to be reappearing in the UITableView after I close and reopen the app. Any suggestions? My code is below. Also, to put this data online, is there a way to use Google Sheets as an online database for my app?

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
}

}

回答1:


At startup you use tableData1 & tableData2 to store information from defaults but classesData and teachersData are initialized to empty. When the app starts it calls numberOfRowsInSection and returns classesData.count which is zero. The other problem you have is that your app will crash the very first time it is ever run because you are initializing it with NSUserDefaults data which is empty. Reset the iOS Simulator then run your app and it will crash. You need to check and handle empty data from NSUserDefaults which is covered here: how to save and read array of array in NSUserdefaults in swift?

I would suggest the following: 1) remove tableData1 & tableData1 and replace with classesData and teachersData everywhere in the app. 2) Create a new function called loadUserDefaults() which is called in viewDidLoad which loads the data from NSUserDefaults while checking for empty NSUserDefaults data. 3) In handleRefresh() just save the data, reload the table view and end refresh. With these suggestions the working code is below.

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]
        }
    }

}


来源:https://stackoverflow.com/questions/34113130/nsuserdefaults-not-working-with-uitableview-in-swift

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!