Swift 中的 NSUserDefaults 无法与 UITableView 一起使用
NSUserDefaults not working with UITableView in Swift
我对 Swift 比较陌生,正在制作一个基本的家庭作业日记应用程序。到目前为止,我所拥有的是嵌入在导航控制器中的 UITableView,该导航控制器嵌入在选项卡栏控制器中。我已经成功地实现了拉动刷新,在 UIAlertView 中添加数据并在刷新后使用此数据填充 table。我需要这个应用程序的持久数据,我听说 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
}
}
启动时,您使用 tableData1 和 tableData2 来存储默认信息,但 classesData 和 teachersData 被初始化为空。当应用程序启动时,它会调用 numberOfRowsInSection 和 returns classesData.count,后者为零。您遇到的另一个问题是,您的应用程序会在第一次 运行 时崩溃,因为您正在使用空的 NSUserDefaults 数据对其进行初始化。重置 iOS 模拟器,然后 运行 您的应用程序,它将崩溃。您需要检查并处理来自 NSUserDefaults 的空数据,这在此处介绍:how to save and read array of array in NSUserdefaults in swift?
我建议如下:
1) 删除 tableData1 & tableData1 并替换为应用程序中各处的 classesData 和 teachersData。
2) 创建一个名为 loadUserDefaults() 的新函数,它在 viewDidLoad 中调用,它从 NSUserDefaults 加载数据,同时检查空的 NSUserDefaults 数据。
3) 在 handleRefresh() 中保存数据,重新加载 table 视图并结束刷新。根据这些建议,工作代码如下。
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]
}
}
}
我对 Swift 比较陌生,正在制作一个基本的家庭作业日记应用程序。到目前为止,我所拥有的是嵌入在导航控制器中的 UITableView,该导航控制器嵌入在选项卡栏控制器中。我已经成功地实现了拉动刷新,在 UIAlertView 中添加数据并在刷新后使用此数据填充 table。我需要这个应用程序的持久数据,我听说 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
}
}
启动时,您使用 tableData1 和 tableData2 来存储默认信息,但 classesData 和 teachersData 被初始化为空。当应用程序启动时,它会调用 numberOfRowsInSection 和 returns classesData.count,后者为零。您遇到的另一个问题是,您的应用程序会在第一次 运行 时崩溃,因为您正在使用空的 NSUserDefaults 数据对其进行初始化。重置 iOS 模拟器,然后 运行 您的应用程序,它将崩溃。您需要检查并处理来自 NSUserDefaults 的空数据,这在此处介绍:how to save and read array of array in NSUserdefaults in swift?
我建议如下: 1) 删除 tableData1 & tableData1 并替换为应用程序中各处的 classesData 和 teachersData。 2) 创建一个名为 loadUserDefaults() 的新函数,它在 viewDidLoad 中调用,它从 NSUserDefaults 加载数据,同时检查空的 NSUserDefaults 数据。 3) 在 handleRefresh() 中保存数据,重新加载 table 视图并结束刷新。根据这些建议,工作代码如下。
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]
}
}
}