2016-06-28 82 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因为字典里是空的。

因此不能附加任何东西。