问题就在这行:
templates[templateItem.templateType!]?.append(templateItem.templateText!)
templates
与这一行初始化:var templates: Dictionary<String, [String]> = [:]
。在这一点上,templates
是一个空的字典。
让我们打破这条线下来到这种情况发生,按时间顺序排列的步骤:
templateItem.templateType
被访问,并强制解开。如果它是nil
,则会发生崩溃。
templateItem.templateType!
被用作templates
字典的关键字。这将始终返回nil
。字典是空的,因此没有任何键的值,包括这个。
?.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
}
注
- 如果
template[text]
不是nil
,它被分配到array
。否则,一个新的数组([]
)被分配给数组。
- 此检查是不必要的
Dictionary<String, [String]>
可以写成只是[String : [String]]
- 无需显式类型signiture
X.init()
可以写成只是X()
- 空虚检查是不必要的,而且整个
for
循环可以变成reduce
呼叫。
备注:不需要检查'!fetchedData.isEmpty'。如果它是空的,那么for循环会迭代0次,这意味着它只会被跳过。 – Alexander