2016-06-28 116 views
0

我在理解二維詞典時遇到了一些問題。我的函數必須返回字典UITableView與部分。 1模板類型可以有多個模板字符串。因此,在fetchedData中有兩個或更多類型相似的文本時,它們必須在數組[String]中使用1個鍵 - 字符串。 從編譯器的角度來看,下面的代碼是絕對正確的。至於我,smth是錯的,但不錯的自動補全讓我覺得一切都好。 顯然它返回一個空的字典[:]Swift 1D Dictionary to 2D

func fetchTemplates() -> Dictionary<String, [String]> { 
    var templates: Dictionary<String, [String]> = [:] 
    let fetchRequest: NSFetchRequest<Template> = Template.fetchRequest() 
    fetchRequest.sortDescriptors = [SortDescriptor.init(key: "templateType", ascending: true)] 
    let fetchedData = try! context.fetch(fetchRequest) 
    if (!fetchedData.isEmpty) { 
     for templateItem in fetchedData { 
      templates[templateItem.templateType!]?.append(templateItem.templateText!) 
     } 
     return templates 
    } 
    else { 
     return templates 
    } 
} 

附: fetchedData回報:

<Template: 0x003281h4> (entity: Template; id: 0x003281h4 <x-coredata:///Template/> ; data: { 
    templateText = "Example"; 
    templateType = "First"; 
}) 
+0

備註:不需要檢查'!fetchedData.isEmpty'。如果它是空的,那麼for循環會迭代0次,這意味着它只會被跳過。 – Alexander

回答

1

問題就在這行:

templates[templateItem.templateType!]?.append(templateItem.templateText!) 

templates與這一行初始化:var templates: Dictionary<String, [String]> = [:]。在這一點上,templates是一個空的字典。

讓我們打破這條線下來到這種情況發生,按時間順序排列的步驟:

  1. templateItem.templateType被訪問,並強制解開。如果它是nil,則會發生崩潰。
  2. templateItem.templateType!被用作templates字典的關鍵字。這將始終返回nil。字典是空的,因此沒有任何鍵的值,包括這個。
  3. ?.append()被調用,條件是它沒有在nil上被調用。如果在nil上呼叫,則不會發生任何事情。

3是您的問題的原因。你需要初始化一個新的數組,如果一個人不爲關鍵存在尚未:

func fetchTemplates() -> Dictionary<String, [String]> { 
    var templates: Dictionary<String, [String]> = [:] 
    let fetchRequest: NSFetchRequest<Template> = Template.fetchRequest() 
    fetchRequest.sortDescriptors = [SortDescriptor.init(key: "templateType", ascending: true)] 
    let fetchedData = try! context.fetch(fetchRequest) 
    if (!fetchedData.isEmpty) { //see note 2 
     for templateItem in fetchedData { 
      let type = templateItem.templateType! 
      var array = templates[type] ?? [] //see note 1 
      array!.append(templateItem.templateText!) 
      templates[type] = array 
     } 
     return templates 
    } 
    else { 
     return templates 
    } 
} 

此功能可以簡化爲:

func fetchTemplates() -> [String : [String]] { 
    let fetchRequest = Template.fetchRequest() 
    fetchRequest.sortDescriptors = [SortDescriptor(key: "templateType", ascending: true)] 

    let fetchedData = try! context.fetch(fetchRequest) 

    var templates = [String, [String]]() 
    for templateItem in fetchedData { 
     let type = templateItem.templateType! 
     templates[type] = (templates[text] ?? []) + [templateItem.templateText!] 
    } 
    return templates 
} 

,並減少可以用來代替:

func fetchTemplates() -> [String : [String]] { //see note 3 
    let fetchRequest = Template.fetchRequest() //see note 4 
    fetchRequest.sortDescriptors = [SortDescriptor(key: "templateType", ascending: true)] //see note 5 

    let fetchedData = try! context.fetch(fetchRequest) 

    return fetchedData.reduce([String, [String]]()){templates, templateItem in 
     (templates[templateItem.tempalteText!] ?? []) + [templateItem.templateText!] 
    } //see note 6 
} 

  1. 如果template[text]不是nil,它被分配到array。否則,一個新的數組([])被分配給數組。
  2. 此檢查是不必要的
  3. Dictionary<String, [String]>可以寫成只是[String : [String]]
  4. 無需顯式類型signiture
  5. X.init()可以寫成只是X()
  6. 空虛檢查是不必要的,而且整個for循環可以變成reduce呼叫。
0

的問題是:

templates[templateItem.templateType!]總是nil因爲字典裏是空的。

因此不能附加任何東西。