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

我有“ScoreHistory.swift”中的以下variables:

// ScoreHistory.swift class ScoreHistory: NSObject, NSCoding { var datePlayed: NSDate var totalScore: Int var totalAnswered: Int var totalDuration: Int var gameStatus: String 

在我的QuizViewController中,我有以下variables:

 // 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. 如何将您的分数历史logging存储到文件中。
  2. 如何从一个视图控制器更改信息到另一个视图控制器。

我不能根据你提供的代码弄清楚。

答案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放在字典中作为string,因为您只想在ScoreViewController中显示它们,并且理解您提供的代码只需要将得分历史作为string显示在单元格中即可。

现在您想要在ScoreViewController中接收通知。 这可以在viewDidLoad,te 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 } } 

我希望这有助于某种方式。