NSUser默认值 - 将3个变量保存在一起,然后获取

时间:2016-10-01 18:49:44

标签: ios swift uitableview nsuserdefaults

我在我的应用中使用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
}

}

2 个答案:

答案 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