我有来自“ 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。
您已正确实现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。
这更加复杂,因为您希望将数据从一个视图控制器获取到另一视图控制器。编码最佳实践表明,您应该使用NSNotifications来通知从一个视图控制器到另一个视图控制器的更改。这对于防止强参考循环是必要的。
这意味着在QuizViewController中,您具有ScoreHistory类的实例。我们称之为“ quizScoreHistory”。在测验期间,实例quizScoreHistory会更新,并且在玩家完成一个关卡时,或者如您所说:“完成会话后”,ScoreViewController需要知道“ quizScoreHistory”的详细信息,以便它可以显示信息给玩家。
我在这里向您展示如何使用字典userInfo作为标准NSNotification来执行此操作。
在类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中实现以下代码,或者更好地将其编写为SetHistory实例中的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/