gpt4 book ai didi

ios - 如何在 Swift 中使用 NSCoding 存储从 ViewController 生成的值

转载 作者:行者123 更新时间:2023-11-30 13:42:39 31 4
gpt4 key购买 nike

我有来自“ScoreHistory.swift”的以下变量:

// ScoreHistory.swift

class ScoreHistory: NSObject, NSCoding {

var datePlayed: NSDate
var totalScore: Int
var totalAnswered: Int
var totalDuration: Int
var gameStatus: String

在我的 QuizViewController 中,我有以下变量:

// QuizViewController.swift

var datePlayed = NSDate()
var totalScore = 0
var totalAnswered = 0
var totalDuration = 0
var gameStatus: String?

每次游戏结束后,用户可能会得到以下信息:(显示在“ScoreViewController”中)

// Example data

datePlayed: (date today)
totalScore: 10
totalAnswered: 15
totalDuration: 1 min. 3 sec.
gameStatus: Exam Finished

我需要从 QuizViewController 获取上述数据以存储到“ScoreHistory.swift”我需要在 ScoreViewController.swift 中显示数据:

// ScoreViewController.swift

class ScoreViewController: UIViewController, UINavigationControllerDelegate {

// in viewDidLoad()

if let score = score {

navigationItem.title = score.datePlayed.description
datePlayedLabel.text = score.datePlayed.description
totalScoreLabel.text = score.totalScore.description
totalAnsweredLabel.text = score.totalAnswered.description
totalDurationLabel.text = score.totalDuration.description
gameStatusLabel.text = score.gameStatus
}

如何将从 QuizViewContoller 生成的数据存储到 ScoreHistory?以及如何将上述数据显示到 ScoreViewController?

我的 ScoreHistory 看起来像这样:

class ScoreHistory: NSObject, NSCoding {

// MARK: Properties

var datePlayed: NSDate
var totalScore: Int
var totalAnswered: Int
var totalDuration: Int
var gameStatus: String

// MARK: Archiving Paths

static let DocumentsDirectory = NSFileManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first!
static let ArchiveURL = DocumentsDirectory.URLByAppendingPathComponent("scores")

// MARK: Types

struct PropertyKey {
static let datePlayedKey = "datePlayed"
static let totalScoreKey = "totalScore"
static let totalAnsweredKey = "totalAnswered"
static let totalDurationKey = "totalDuration"
static let gameStatusKey = "gameStatus"
}

// MARK: Initialization

init?(datePlayed: NSDate, totalScore: Int, totalAnswered: Int, totalDuration: Int, gameStatus: String) {
// Initialize stored properties.

self.datePlayed = datePlayed
self.totalScore = totalScore
self.totalAnswered = totalAnswered
self.totalDuration = totalDuration
self.gameStatus = gameStatus


super.init()

// Initialization should fail if there is no name or if the rating is negative.
if gameStatus.isEmpty {
return nil
}
}

// MARK: NSCoding

func encodeWithCoder(aCoder: NSCoder) {

aCoder.encodeObject(datePlayed, forKey: PropertyKey.datePlayedKey)
aCoder.encodeInteger(totalScore, forKey: PropertyKey.totalScoreKey)
aCoder.encodeInteger(totalAnswered, forKey: PropertyKey.totalAnsweredKey)
aCoder.encodeInteger(totalDuration, forKey: PropertyKey.totalDurationKey)
aCoder.encodeObject(gameStatus, forKey: PropertyKey.gameStatusKey)
}

required convenience init?(coder aDecoder: NSCoder) {

let datePlayed = aDecoder.decodeObjectForKey(PropertyKey.datePlayedKey) as? NSDate
let totalScore = aDecoder.decodeIntegerForKey(PropertyKey.totalScoreKey)
let totalAnswered = aDecoder.decodeIntegerForKey(PropertyKey.totalAnsweredKey)
let totalDuration = aDecoder.decodeIntegerForKey(PropertyKey.totalDurationKey)
let gameStatus = aDecoder.decodeObjectForKey(PropertyKey.gameStatusKey) as! String

// Must call designated initializer.
self.init(datePlayed: datePlayed!, totalScore: totalScore, totalAnswered: totalAnswered, totalDuration: totalDuration, gameStatus: gameStatus)
}

}

最佳答案

我不确定我是否正确理解了您的问题。您的问题是:

  1. 如何将您的分数历史记录存储到文件中。
  2. 如何将更改的信息从一个 View Controller 获取到另一个 View Controller 。

根据您提供的代码我无法弄清楚。

回答1。您在 ScoreHistory 类中正确实现了 NSCoding 方法。我在这里假设这是您的模型类,它必须保存在整个游戏中收集的数据。要将数据保存到文件中,您只需使用 NSKeyedArchiver 对象即可。代码示例如下:

    func saveStatisticsToDisk() {
let isSuccessfulSave = NSKeyedArchiver.archiveRootObject(savedScore, toFile: ScoreHistory.scoreStore.path!)

if !isSuccessfulSave {
//Set the alert properties.
let title = "Warning"
let message = "Unable to save the scores"
let animationFlag = true

//configure the alert.
let alertMessage = UIAlertController.init(title: title, message: message, preferredStyle: .Alert)
let okAction = UIAlertAction(title: "Ok", style: .Default) {
(action) -> Void in
self.presentingViewController?.dismissViewControllerAnimated(animationFlag, completion: nil)
}
alertMessage.addAction(okAction)

//Present the alert.
self.presentViewController(alertMessage, animated: animationFlag, completion: nil)
}
}

回答2。这比较复杂,因为您想要将数据从一个 View Controller 获取到另一个 View Controller 。编码最佳实践告诉您应该使用 NSNotifications 将更改从一个 View Controller 发送到另一个 View Controller 。这对于防止强引用循环是必要的。

这意味着在 QuizViewController 中您有一个 ScoreHistory 类的实例。我们称之为“quizScoreHistory”。在测验期间,实例 quizScoreHistory 会更新,当玩家完成一个关卡时,或者如您所说:“完成 session 后”,ScoreViewController 需要知道“quizScoreHistory”的详细信息是什么,以便它可以显示信息给玩家。

我在这里向您展示如何使用标准 NSNotification 的字典 use​​rInfo 来完成此操作。在 QuizViewController 类中,您使用以下代码将通知放置在默认通知中心:

    func notifyOnTrackChanges() {
//This function makes a dictionary with the key value pairs that reflect your ScoreHistory class.
//The a notification is posted under the name "scoreDidChange" posting the dictionary as userInfo.
//The ScoreOverviewController will pick this up and store the values in the score to be displayed.

let userInfo : [String: String] = ["date played": dateformatter.stringFromDate((self.quizScoreHistory.datePlayed)!), "total score": String((self.quizScoreHistory.totalScore)!), "total answered": String((self.quizScoreHistory.totalAnswered)!), "total duration": String((self.quizScoreHistory.gameStatus)!), "game status": String((self.quizScoreHistory.gameStatus)!)]
let trackDetailNotificationCenter = NSNotificationCenter.defaultCenter()
trackDetailNotificationCenter.postNotificationName("scoreDidChange", object: self, userInfo: userInfo)
}

我将 userInfo 作为字符串放入字典中,因为您只想在 ScoreViewController 中显示它们并理解您提供的代码,您只需要以字符串形式获取分数历史记录即可将其显示在单元格中。

现在您想在 ScoreViewController 中接收通知。可以在 viewDidLoad、viewWillAppear 中实现以下代码,或者更好地将其编写为 ScoreHistory 实例中的 setter。

        //This is the observer created to get the changes back from the QuizViewController.
let notificationCenter = NSNotificationCenter.defaultCenter()
let operationsQueue = NSOperationQueue.mainQueue()
self.scoreChangedObserver = notificationCenter.addObserverForName("scoreDidChange", object: nil, queue: operationsQueue, usingBlock: { (notification: NSNotification!) -> Void in

let score.datePlayed = notification.userInfo!["date played"]!
let score.totalScore = notification.userInfo!["total score"]!
let score.totalAnswered = notification.userInfo!["total answered"]!
let score.totalDuration = notification.userInfo!["total duration"]!
let score.gameStatus = notification.userInfo!["gameStatus"]!

self.displayScore()
})

假设分数是该方法的属性,您的显示分数可能会像您在问题中提供的那样:

func displayScore() {
if let score = score {

navigationItem.title = score.datePlayed
datePlayedLabel.text = score.datePlayed
totalScoreLabel.text = score.totalScore
totalAnsweredLabel.text = score.totalAnswered
totalDurationLabel.text = score.totalDuration
gameStatusLabel.text = score.gameStatus
}
}

我希望这能在某种程度上有所帮助。

关于ios - 如何在 Swift 中使用 NSCoding 存储从 ViewController 生成的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35381702/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com