我在我的应用中使用NSUserDefaults
进行持久存储。这是一种游戏,在游戏结束后,必须存储分数以及日期和名称(由用户输入),然后在表格视图中显示。到目前为止我的代码是:
import UIKit
class LeaderboardVC: UIViewController, UITableViewDataSource, UITableViewDelegate {
var finishedGame = 0
var gameScore:Int! = 0
var name:String!
var date:String!
var score:Int!
var scoreData = [NSArray]()
var defaults = UserDefaults.standard
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
if finishedGame == 1{
saveNew()
}
self.tableView.delegate = self
self.tableView.dataSource = self
}
override func viewWillAppear(_ animated: Bool) {
self.navigationController?.isNavigationBarHidden = false
self.navigationItem.hidesBackButton = true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func saveNew() {
let enterNameAlert = UIAlertController(title: "Please Enter Your Name", message: "This will be used to place you in the leaderboards", preferredStyle: .alert)
enterNameAlert.addTextField { (textField:UITextField) -> Void in
textField.placeholder = "Name"
textField.autocapitalizationType = UITextAutocapitalizationType.words
textField.autocorrectionType = UITextAutocorrectionType.no
textField.clearsOnBeginEditing = true
textField.clearsOnInsertion = true
textField.clearButtonMode = UITextFieldViewMode.always
textField.keyboardType = UIKeyboardType.default
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
let confirmAction = UIAlertAction(title: "Confirm", style: .default) { (action:UIAlertAction) in
let currentTime = Date()
let timeFormatter = DateFormatter()
timeFormatter.locale = Locale.current
timeFormatter.dateFormat = "HH:mm dd/MM/yy"
let convertedTime = timeFormatter.string(from: currentTime) //date
let enteredName = enterNameAlert.textFields?.first?.text //name
// set object of date,name and score here
}
enterNameAlert.addAction(cancelAction)
enterNameAlert.addAction(confirmAction)
self.present(enterNameAlert, animated: true, completion: nil)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! LeaderBoardCell
cell.dateLabel?.text =
cell.dateLabel.adjustsFontSizeToFitWidth = true
cell.scoreLabel?.text =
cell.scoreLabel.adjustsFontSizeToFitWidth = true
cell.nameLabel?.text =
cell.nameLabel.adjustsFontSizeToFitWidth = true
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return scoreData.count
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
}
单元格中有3个标签,每个标签必须显示3个值。如何使用NSUserDefaults
设置这些值(它们必须在一起例如得分:500与名称:约翰等等)?
编辑 - 新代码
import UIKit
class LeaderboardVC:UIViewController,UITableViewDataSource,UITableViewDelegate {
var finishedGame = 0
var gameScore:Int! = 0
var defaults = UserDefaults.standard
var newUserArray = NSMutableArray()
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
if finishedGame == 1{
saveNew()
}
self.tableView.delegate = self
self.tableView.dataSource = self
}
override func viewWillAppear(_ animated: Bool) {
self.navigationController?.isNavigationBarHidden = false
self.navigationItem.hidesBackButton = true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func saveNew() {
let enterNameAlert = UIAlertController(title: "Please Enter Your Name", message: "This will be used to place you in the leaderboards", preferredStyle: .alert)
enterNameAlert.addTextField { (textField:UITextField) -> Void in
textField.placeholder = "Name"
textField.autocapitalizationType = UITextAutocapitalizationType.words
textField.autocorrectionType = UITextAutocorrectionType.no
textField.clearsOnBeginEditing = true
textField.clearsOnInsertion = true
textField.clearButtonMode = UITextFieldViewMode.always
textField.keyboardType = UIKeyboardType.default
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
let confirmAction = UIAlertAction(title: "Confirm", style: .default) { (action:UIAlertAction) in
let currentTime = Date()
let timeFormatter = DateFormatter()
timeFormatter.locale = Locale.current
timeFormatter.dateFormat = "HH:mm dd/MM/yy"
let convertedTime = timeFormatter.string(from: currentTime)
let enteredName = enterNameAlert.textFields?.first?.text
let newUserData = self.defaults.object(forKey: "UserData") as! NSArray
let newUserArray = NSMutableArray(array: newUserData)
let newUserRecord = [
"Name" : enteredName!,
"Score" : String(self.gameScore),
"Date" : convertedTime
] as [String : String]
newUserArray.add(newUserRecord)
self.defaults.set(newUserArray, forKey: "UserData")
self.defaults.synchronize()
print(newUserArray)
print("hello")
print(self.defaults)
}
enterNameAlert.addAction(cancelAction)
enterNameAlert.addAction(confirmAction)
self.present(enterNameAlert, animated: true, completion: nil)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! LeaderBoardCell
let userData = defaults.object(forKey: "UserData") as! NSArray
cell.dateLabel?.text = "Date: \(((userData.object(at: indexPath.row) as! [String:Any])["Date"] as! String))"
cell.dateLabel.adjustsFontSizeToFitWidth = true
cell.scoreLabel?.text = "Score: \(((userData.object(at: indexPath.row) as! [String:Any])["Score"] as! String))"
cell.scoreLabel.adjustsFontSizeToFitWidth = true
cell.nameLabel?.text = "Name: \(((userData.object(at: indexPath.row) as! [String:Any])["Name"] as! String))"
cell.nameLabel.adjustsFontSizeToFitWidth = true
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return newUserArray.count
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
}
答案 0 :(得分:0)
您可以将字典设置为UserDefaults(一次为3个值设置)。要做排行榜,你需要将这些词典放在数组中。
let scoreDict: [String : Any] = ["name": "John", "score": 500, "date": NSDate()]
let defaults = UserDefaults.standard
let scoresKey = "scores"
var currentScores: [Any] = defaults.array(forKey: scoresKey) ?? []
currentScores.append(scoreDict)
defaults.set(currentScores, forKey: scoresKey)
defaults.synchronize()
答案 1 :(得分:0)
我无法获得尽可能多的内容,但我发现您需要为tableview数据源添加一些元素scoreData
您可以在此处添加UserDefaults
//Make your scoreData as MutableArray
var scoreData = NSMutableArray()
// Record of a user
let user = [
"name" : "John",
"score" : 10,
"id" : 20
] as [String : Any]
scoreData.add(user)
defaults.set(scoreData, forKey: "UserData")
如何获取它们
let userData = defaults.object(forKey: "UserData") as! NSArray
print((userData.object(at: 0) as! [String:Any])["name"] as! String)
print((userData.object(at: 0) as! [String:Any])["score"] as! Int)
print((userData.object(at: 0) as! [String:Any])["id"] as! Int)
我在控制台上打印了它们,只有第0个索引。您可以使用indexPath.row
元素在标签上打印它们。
修改强>
要添加新记录,请首先从userDefaults
let newUserData = defaults.object(forKey: "UserData") as! NSArray
然后将其转换为可变数组,因为我们要添加新的用户记录。我可以在获取时完成它,但是从UserDefaults
获取时,无论我们是否输入NSMutableArray
,它都会提供一个不可变对象。因此,将newUserData
转换为可变对象
let newUserMutableArray = NSMutableArray(array: newUserData)
添加新记录
// New record
let newUserRecord = [
"name" : "Rajan",
"score" : 20,
"id" : 30
] as [String : Any]
newUserMutableArray.add(newUserRecord)
再次保存
defaults.set(newUserMutableArray, forKey: "UserData")
再次获取上面提到的方式。现在,提取的NSArray
将包含两个元素
在这种情况下,我仍然更喜欢使用核心数据,因为处理将变得非常容易。
修改强>
拿取后
scoreDataArray = defaults.object(forKey: "UserData") as! NSArray
重新加载你的桌子
self.yourTableView.reloadData()
您的表视图数据源方法将类似于
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return scoreDataArray.count
}
在cellForRowAt
数据源方法
cell.scoreLabel?.text = scoreDataArray.object(at: indexPath.row) as! [String:Any])["score"] as! String