问题描述
我对 Swift 比较陌生,正在制作一个基本的家庭作业日记应用.到目前为止,我所拥有的是嵌入在导航控制器中的 UITableView,该导航控制器嵌入在标签栏控制器中.我已经成功地实现了拉动刷新,在 UIAlertView 中添加数据并在刷新后用这些数据填充表.我需要这个应用程序的持久数据,我听说 NSUserDefaults 是最好的方法,但它对我不起作用.我可以看到它正在添加到 NSUserDefaults,但在我关闭并重新打开应用程序后,它似乎没有重新出现在 UITableView 中.有什么建议么?我的代码如下.此外,要将这些数据放到网上,是否可以将 Google 表格用作我的应用的在线数据库?
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
}
}
推荐答案
在启动时你使用 tableData1 &tableData2 用于存储来自默认值的信息,但 classesData 和教师数据被初始化为空.当应用程序启动时,它调用 numberOfRowsInSection 并返回 classesData.count,它为零.您遇到的另一个问题是您的应用程序将在第一次运行时崩溃,因为您使用空的 NSUserDefaults 数据对其进行初始化.重置 iOS 模拟器,然后运行您的应用程序,它会崩溃.您需要检查和处理来自 NSUserDefaults 的空数据,这里介绍:如何在 swift 中保存和读取 NSUserdefaults 中的数组数组?
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?
我建议如下:1) 删除 tableData1 &tableData1 并替换为应用程序中随处可见的 classesData 和教师数据.2) 创建一个名为 loadUserDefaults() 的新函数,该函数在 viewDidLoad 中调用,该函数从 NSUserDefaults 加载数据,同时检查空 NSUserDefaults 数据.3) 在handleRefresh() 中只保存数据,重新加载表视图并结束刷新.根据这些建议,工作代码如下.
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]
}
}
}
这篇关于NSUserDefaults 不适用于 Swift 中的 UITableView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!