2017-05-14 30 views
0

我正在編寫一個應用程序來顯示和瀏覽一系列使用Swift的問題和答案。我目前有一個問題詞典和相關答案,然後我通過使用.map創建一個'flashcard'對象(每個對象都有一個問題,它是相關的答案)。爲什麼我的數組不是從第一個映射到它的項開始的? Swift

當我然後從數組中訪問這些對象時,出於某種原因,返回的第0項似乎是我的字典中的第二項,而不是第一項(例如'問題2')。有人可以解釋爲什麼這是嗎?這是其產生數據的排列,並提供給項返回到相關的視圖控制器的裝置的類:

import Foundation 

class Deck { 
    // Create constant to hold the deck of cards 
    private var cards: [Flashcard] 
    var bookmark: Int // Remembers which card we are on 


    init() { 
     let cardData = ["Question 1" : "Answer 1", 
         "Question 2" : "Answer 2", 
         "Question 3" : "Answer 3"] 

     cards = cardData.map { Flashcard(question: $0, answer: $1) } 
     bookmark = 0 // Start with bookmark on first item in deck 
    } 

    // Getter method to return current card 
    public func getCurrentCard() -> Flashcard { 
     print("Bookmark set to \(bookmark)") 
     return cards[bookmark] 
    } 

    // Getter method to return the next card in the deck 
    public func getNextCard() -> Flashcard { 
     bookmark += 1 
     print("Bookmark set to \(bookmark)") 
     return cards[bookmark] 
    } 

    // Getter method to return previous card in deck 
    public func getLastCard() -> Flashcard { 
     bookmark -= 1 
     print("Bookmark set to \(bookmark)") 
     return cards[bookmark] 
    } 
} 

然後,這是我的視圖控制器,其中我請求的對象被顯示:

import UIKit 

class QuestionController: UIViewController { 

    // Outlet for the 'question' label 
    @IBOutlet weak var questionTextView: UITextView! 

    // Outlet for the next button 
    @IBAction func nextQuestion(_ sender: UIButton) { 
     flashcard = deck.getNextCard() 
     questionTextView.text = flashcard?.question 

    } 

    // Outlet for last button 
    @IBAction func lastQuestion(_ sender: UIButton) { 
     flashcard = deck.getLastCard() 
     questionTextView.text = flashcard?.question 
    } 



    // variable to hold current flashcard 
    var flashcard: Flashcard? 
    let deck = Deck() // Holds deck of data 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     // Do any additional setup after loading the view, typically from a nib. 
     flashcard = deck.getCurrentCard() 
     questionTextView.text = flashcard?.question 

    } 

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



// Prepare flashcard item to be passed to the answer controller before segue 
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 
     if let answerController = segue.destination as? AnswerController { 
      answerController.flashcard = flashcard 
     } 
    } 

} 

當我運行應用程序時,顯示的第一個問題是「問題2」,當我期待它成爲「問題1」...?

+0

相關:[有序字典在Swift](http://stackoverflow.com/questions/30969688/ordered-dictionary-in-swift)。 –

回答

3

的問題是,鍵值對的一個Dictionary順序是未指定 - 這完全取決於執行,並不能保證是相同的,其中鍵值對出現在字典中的文字順序你用來創建字典。

你的情況簡單的解決方案是使用,而不是一本字典,而是一個DictionaryLiteral - 它保持鍵值對的順序:

init() { 
    let cardData: DictionaryLiteral = ["Question 1" : "Answer 1", 
             "Question 2" : "Answer 2", 
             "Question 3" : "Answer 3"] 

    cards = cardData.map { Flashcard(question: $0, answer: $1) } 
    bookmark = 0 // Start with bookmark on first item in deck 
} 

這是因爲under the hoodDictionaryLiteral只不過是一個更鍵值元組數組。正因爲如此,你會發現,它的表現非常不同在一個Dictionary,以及維護鍵值對的順序:

  • 它有一個從零開始的Int的索引,您可以用
  • 下標
  • 它不需要的鑰匙,是Hashable
  • 它允許重複鍵
  • 鍵查找發生在直線(不是常數)時間

其主要因此,在將鍵值對包裝到實際的數據結構中之前,使用它實際上只是一些短暫的語法糖(允許使用字典文字) - 我們在這裏如何使用它。

+0

感謝Hamish,我想知道它是否可能與此有關,但是想到也許它會隨機從每個應用程序運行的不同對象開始,而它總是從第二項開始。 – laurie

+0

@laurie快樂的幫助:)值得注意的是,即使依賴於* same *程序的執行之間的'Dictionary'中的鍵值對的順序也沒有依賴 - 因爲'Hashable'協議不保證在不同的執行過程中爲同一個實例返回的散列值將是穩定的(這在文檔中特別註明)。 – Hamish

+0

你好@Hamish,你認爲一組定製模型會更好嗎?順便說一句,最後我看到'DictionaryLiteral'有用的用法謝謝你的答案。 –

相關問題