問題就在這行:
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