2016-02-13 38 views
0

使用NSCoding一個視圖控制器產生的價值我有一個從「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) 
} 

} 
+0

你會忽略你的類ScoreHistory的最重要的部分,你都應該實現NSCoding編碼器和解碼器 –

+0

@LeoDabus,我更新了我的問題,請您檢查 – mjoe7

+0

你可以開始改變你的文件的名稱scores.plist –

回答

0

我不知道我正確理解你的問題。是你的問題:

  1. 如何將你的分數歷史存儲到文件。
  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這裏串在字典中,因爲你只需要diaplay他們在ScoreViewController和理解您提供的代碼只需要將得分記錄作爲字符串顯示在單元格中。

現在您想要在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 
    } 
} 

我希望這有助於以某種方式。

+0

謝謝,我會嘗試它,並會讓你知道:) – mjoe7