使用NSUserDefaults保存标签的文本

时间:2022-06-18 04:10:26

I'm trying to save my score with NSUserDefaults. I want it to save the labels text, so when you open it back up the text is still there. I don't know where the code should go. Any help is much appreciated.

我正试图用NSUserDefaults保存我的分数。我希望它保存标签文本,所以当你打开它时,文本仍然存在。我不知道代码应该去哪里。任何帮助深表感谢。

Here's my code:

这是我的代码:

import UIKit
import AVFoundation

struct Question {
    var Question : String!
    var Answers : [String]!
    var Answer : Int!
}

class ViewController: UIViewController {
    @IBOutlet weak var highScoreLbl: UILabel!
    @IBOutlet var Buttons: [UIButton]!
    @IBOutlet weak var QLabel: UILabel!
    @IBOutlet weak var Label: UILabel!
    @IBOutlet weak var incorrectLabel: UILabel!
    @IBOutlet weak var timerLabel: UILabel!
    @IBOutlet weak var theEnd: UILabel!
    @IBOutlet weak var continueButton: UIButton!
    @IBOutlet weak var button1: UIButton!
    @IBOutlet weak var button2: UIButton!
    @IBOutlet weak var button3: UIButton!
    @IBOutlet weak var button4: UIButton!

    var scoreLbl = UILabel()
    var score = Int()
    var Questions = [Question]()
    var QNumber = Int()
    var AnswerNumber = Int()
    var wrongAnswers = Int()
    var highScore = 0

    override func viewDidLoad() {
        super.viewDidLoad()

        Questions = [Question(Question: "What is the Biggest Hit of Bing Crosby?" , Answers: ["Swinging on a Star", "Now is the Hour", "White Christmas", "Beautiful Dreamer"], Answer: 2),
        Question(Question: "What is Elvis Presely's Middle Name?", Answers: ["Aaron", "Micheal", "George", "Matthew"], Answer: 0),
        Question(Question: "How Many Oscars did Titanic win?", Answers: ["5", "7", "10", "11"], Answer: 3),
        Question(Question: "From which country did Pitta Bread originate?", Answers: ["Spain", "France", "Greece", "Russia"], Answer: 2),
        Question(Question: "What is the largest living creature on Earth?", Answers: ["Whale", "Shark", "Sea Turtle", "Alligator"], Answer: 0),
        Question(Question: "What does ATM stand for?", Answers: ["Automatic Treasure Machine", "Automatic Tax Machine", "Anti Tax Machine", "Automatic Teller Machine"], Answer: 3),
        Question(Question: "What's the world's second largest French speaking city?", Answers: ["Paris", "Montreal", "Versailles", "Québec"], Answer: 1),
        Question(Question: "What Country is the largest producer of Olive Oil?", Answers: ["Italy", "France", "Greece", "Spain"], Answer: 3),
        Question(Question: "How long is the Great Wall of China?", Answers: ["3200 miles", "4000 miles", "2000 kilometers", "4500 miles"], Answer: 1),
        Question(Question: "Who is on the 10 dollar bill?", Answers: ["George Washington", "Thomas Jefferson", "Alexander Hamilton", "John Adams" ], Answer: 2),
        Question(Question: "How many World Series did Yogi Berra win as a player?", Answers: ["11", "10", "5", "7" ], Answer: 1),
        Question(Question: "Which three countries hosted the Winter Olympics during the 1990's?", Answers: ["Norway, France, Russia", "US, Sweeden, Canada", "Japan, Canada, Germany", "Slovenia, France, South Korea" ], Answer: 0),]

        scoreLbl = UILabel(frame: CGRectMake(35, 45, 77, 45))
        scoreLbl.textAlignment = NSTextAlignment.Center
        scoreLbl.text = "-1"
        self.view.addSubview(scoreLbl)

        PickQuestions()

        saveHighScore()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func PickQuestions(){

        score++
        scoreLbl.text = "\(score)"

        if Questions.count > 0{
            QNumber = random() % Questions.count
            QLabel.text = Questions[QNumber].Question

            AnswerNumber = Questions[QNumber].Answer

            for i in 0..<Buttons.count{
                Buttons[i].setTitle(Questions[QNumber].Answers[i], forState: UIControlState.Normal)
            }

            Questions.removeAtIndex(QNumber)
        }
        else{

            theEnd.text = "You Win!"
            theEnd.alpha = 1
            button1.enabled = false
            button2.enabled = false
            button3.enabled = false
            button4.enabled = false

            func reset(){
                let alert = UIAlertController(title: "You Win", message: "Click Restart To Play Again", preferredStyle: UIAlertControllerStyle.Alert)
                let okAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: nil)
                alert.addAction(okAction)
                presentViewController(alert, animated: true, completion: nil)
            }
            reset()
        }

        saveHighScore()
        incorrectLabel.alpha = 0

    }

    func saveHighScore(){

        if score >= highScore {
            highScore = score
            highScoreLbl.text = "High Score: " + String(score)

        }
        else{}

    }
    @IBAction func Btn1(sender: AnyObject) {
        if AnswerNumber == 0{
            PickQuestions()
        }
        else{
            incorrectLabel.text = "You are incorrect!"
            incorrectLabel.alpha = 1
            score--
            scoreLbl.text = "\(score)"
        }

    }
    @IBAction func Btn2(sender: AnyObject) {
        if AnswerNumber == 1{

            PickQuestions()
        }
        else{
            incorrectLabel.text = "You are Incorrect!"
            incorrectLabel.alpha = 1
            score--
            scoreLbl.text = "\(score)"
        }
    }
    @IBAction func Btn3(sender: AnyObject) {
        if AnswerNumber == 2{

            PickQuestions()
        }
        else{
            incorrectLabel.text = "You are Incorrect!"
            incorrectLabel.alpha = 1
            score--
            scoreLbl.text = "\(score)"
        }
    }
    @IBAction func Btn4(sender: AnyObject) {
        if AnswerNumber == 3{

            PickQuestions()
        }
        else{
            incorrectLabel.text = "You are Incorrect!"
            incorrectLabel.alpha = 1
            score--
            scoreLbl.text = "\(score)"
        }
    }
}

2 个解决方案

#1


0  

You could do it using property observers. Each time you set your score, your didSet block will check if your score is greater than the previous highscore, if it is it will run and store your high score into your NSUserDefaults.

你可以使用属性观察者来做到这一点。每次设置分数时,didSet块都会检查您的分数是否大于之前的分数,如果它会运行并将您的高分存储到您的NSUserDefaults中。

"Property observers observe and respond to changes in a property’s value. Property observers are called every time a property’s value is set, even if the new value is the same as the property’s current value."

“物业观察者观察并回应物业价值的变化。每次设置物业的价值时,即使新值与物业的当前价值相同,也会调用物业观察员。”

More information on property observers: Swift Programming Language Guide

有关属性观察者的更多信息:Swift编程语言指南

var userDefaults = NSUserDefaults.standardUserDefaults()

var score: Int = 0 {
        didSet {
            self.scoreLbl.text = "\(score)"

            if score > highScore {
                // you could just as easily call a function here
                userDefaults.setInteger(score, forKey: "CurrentHighScore")
                //userDefaults.synchronize() // slow and unnecessary!
            } 
        }
    }

Then in your viewDidLoad or viewWillAppear retrieve your high-score value:

然后在viewDidLoad或viewWillAppear中检索您的高分值:

override func viewDidLoad() {

    self.scoreLbl.text = userDefaults.integerForKey("CurrentHighScore")

}

Synchronize is not necessary iOS 8 and later:

iOS 8及更高版本不需要同步:

from http://www.codingexplorer.com/nsuserdefaults-a-swift-introduction/

Calling synchronize in an iOS 8 app will unnecessarily slow your program, without giving a significant benefit. I’ll let the document speak for itself about the Performance Tradeoffs in NSUserDefaults:

在iOS 8应用程序中调用同步将不必要地减慢您的程序,而不会带来显着的好处。我将让文档说明NSUserDefaults中的性能权衡:

"Reading from NSUserDefaults is extremely fast. It will cache values to avoid reading from the disk, and takes about 0.5 microseconds to do [[NSUserDefaults standardUserDefaults] boolForKey:] on a 2012 MacBook Pro. It’s generally unnecessary (and even undesirable since it prevents picking up new values) to cache the result of reading from preferences.

“从NSUserDefaults读取速度非常快。它将缓存值以避免从磁盘读取,并且在2012 MacBook Pro上执行[[NSUserDefaults standardUserDefaults] boolForKey:]需要大约0.5微秒。这通常是不必要的(甚至是不可取的,因为它可以防止获取新值)以缓存从首选项中读取的结果。

However, writing to NSUserDefaults is a bit slower. In general, expect it to take roughly as long as using NSPropertyListSerialization to convert your key and value to plist data, plus a few 10s of microseconds. For this reason, as well as memory usage, it’s generally best to store relatively small data in CFPreferences."

但是,写入NSUserDefaults有点慢。一般来说,预计使用NSPropertyListSerialization将密钥和值转换为plist数据加上几十微秒的时间大致相同。出于这个原因,以及内存使用,通常最好在CFP参考中存储相对较小的数据。“

#2


0  

You should combine everything that comes with changing the score into one method. That would be easier for you to manage and would make for a much cleaner code

您应该将改变分数的所有内容组合到一个方法中。这对您来说更容易管理,并且可以使代码更清晰

func saveScore(newScore:Int){
    // Set the value of newScore to the class variable score
    score = newScore

    // Set the value of newScore to the scoreLbl
    scoreLbl.text = "\(newScore)"

    // Fetch User Defauls
    let userDefaults = NSUserDefaults.standardUserDefaults()

    // Save newScore value to the userDefaults
    userDefaults.setInteger(newScore, forKey: "score")

    // Synchronize userDefaults
    userDefaults.synchronize()
}

This method will set the score, put it in the label and save the score to the user defaults at the same time. Just call this method whenever you want to update score instead of changing the value of score directly.

此方法将设置分数,将其放在标签中并同时将分数保存到用户默认值。只要您想更新分数而不是直接更改分数值,就可以调用此方法。

#1


0  

You could do it using property observers. Each time you set your score, your didSet block will check if your score is greater than the previous highscore, if it is it will run and store your high score into your NSUserDefaults.

你可以使用属性观察者来做到这一点。每次设置分数时,didSet块都会检查您的分数是否大于之前的分数,如果它会运行并将您的高分存储到您的NSUserDefaults中。

"Property observers observe and respond to changes in a property’s value. Property observers are called every time a property’s value is set, even if the new value is the same as the property’s current value."

“物业观察者观察并回应物业价值的变化。每次设置物业的价值时,即使新值与物业的当前价值相同,也会调用物业观察员。”

More information on property observers: Swift Programming Language Guide

有关属性观察者的更多信息:Swift编程语言指南

var userDefaults = NSUserDefaults.standardUserDefaults()

var score: Int = 0 {
        didSet {
            self.scoreLbl.text = "\(score)"

            if score > highScore {
                // you could just as easily call a function here
                userDefaults.setInteger(score, forKey: "CurrentHighScore")
                //userDefaults.synchronize() // slow and unnecessary!
            } 
        }
    }

Then in your viewDidLoad or viewWillAppear retrieve your high-score value:

然后在viewDidLoad或viewWillAppear中检索您的高分值:

override func viewDidLoad() {

    self.scoreLbl.text = userDefaults.integerForKey("CurrentHighScore")

}

Synchronize is not necessary iOS 8 and later:

iOS 8及更高版本不需要同步:

from http://www.codingexplorer.com/nsuserdefaults-a-swift-introduction/

Calling synchronize in an iOS 8 app will unnecessarily slow your program, without giving a significant benefit. I’ll let the document speak for itself about the Performance Tradeoffs in NSUserDefaults:

在iOS 8应用程序中调用同步将不必要地减慢您的程序,而不会带来显着的好处。我将让文档说明NSUserDefaults中的性能权衡:

"Reading from NSUserDefaults is extremely fast. It will cache values to avoid reading from the disk, and takes about 0.5 microseconds to do [[NSUserDefaults standardUserDefaults] boolForKey:] on a 2012 MacBook Pro. It’s generally unnecessary (and even undesirable since it prevents picking up new values) to cache the result of reading from preferences.

“从NSUserDefaults读取速度非常快。它将缓存值以避免从磁盘读取,并且在2012 MacBook Pro上执行[[NSUserDefaults standardUserDefaults] boolForKey:]需要大约0.5微秒。这通常是不必要的(甚至是不可取的,因为它可以防止获取新值)以缓存从首选项中读取的结果。

However, writing to NSUserDefaults is a bit slower. In general, expect it to take roughly as long as using NSPropertyListSerialization to convert your key and value to plist data, plus a few 10s of microseconds. For this reason, as well as memory usage, it’s generally best to store relatively small data in CFPreferences."

但是,写入NSUserDefaults有点慢。一般来说,预计使用NSPropertyListSerialization将密钥和值转换为plist数据加上几十微秒的时间大致相同。出于这个原因,以及内存使用,通常最好在CFP参考中存储相对较小的数据。“

#2


0  

You should combine everything that comes with changing the score into one method. That would be easier for you to manage and would make for a much cleaner code

您应该将改变分数的所有内容组合到一个方法中。这对您来说更容易管理,并且可以使代码更清晰

func saveScore(newScore:Int){
    // Set the value of newScore to the class variable score
    score = newScore

    // Set the value of newScore to the scoreLbl
    scoreLbl.text = "\(newScore)"

    // Fetch User Defauls
    let userDefaults = NSUserDefaults.standardUserDefaults()

    // Save newScore value to the userDefaults
    userDefaults.setInteger(newScore, forKey: "score")

    // Synchronize userDefaults
    userDefaults.synchronize()
}

This method will set the score, put it in the label and save the score to the user defaults at the same time. Just call this method whenever you want to update score instead of changing the value of score directly.

此方法将设置分数,将其放在标签中并同时将分数保存到用户默认值。只要您想更新分数而不是直接更改分数值,就可以调用此方法。