最近我在一本书中看到了以下代码行(关于CoreData)
return modelURLs(in: modelName).compactMap(NSManagedObjectModel.init)
我知道代码的作用,但问题是:为什么以及如何工作? 应该有一个闭包作为compactMap函数的参数,但是在 NORMAL 括号中只有一个“ NSManagedObjectModel.init”。这有什么秘诀?在那里做什么?如果有一个称为init的静态/类属性,它返回一个闭包,但我认为不存在,那么我会理解。
不幸的是,这本书没有更多地介绍这一行代码。我想从Apple文档中进一步阅读,但找不到任何内容。当我在Google上搜索“对闭包进行初始化”时,没有得到有用的结果。
所以你们是我最后的希望:)
顺便说一句:modelURLs(in:modelName)函数返回一个URL数组,但这在这里并不是很重要。
答案 0 :(得分:3)
使用闭包时,可以使用不同的语法,如下面的示例所示,该示例将int数组转换为字符串数组
let array = [1, 2, 3]
以下对compactMap
的调用将正确转换数组并产生相同的结果
let out1 = array.compactMap({return String($0)})
let out2 = array.compactMap({String($0)})
let out3 = array.compactMap {String($0)}
let out4 = array.compactMap(String.init)
当有两个采用相同数量和类型参数的init方法时,则必须添加完整签名以供init方法使用。考虑这个简单的示例结构
struct TwoTimesInt: CustomStringConvertible {
let value: Int
let twiceTheValue: Int
var description: String {
return "\(value) - \(twiceTheValue)"
}
init(value: Int) {
self.value = value
self.twiceTheValue = 2 * value
}
}
我们只有1种初始化方法可以做到
let out5 = array.compactMap(TwoTimesInt.init)
但是如果我们添加第二个init方法
init(twiceTheValue: Int) {
self.value = twiceTheValue / 2
self.twiceTheValue = twiceTheValue
}
然后我们需要给出要使用的init方法的完整签名
let out6 = array.compactMap( TwoTimesInt.init(value:) )
关于选择哪种方法,值得一提的另一件事是查看初始化方法包括的完整签名,如果它返回一个可选值。例如,如果我们更改第二个init方法的签名以返回可选值
init?(twiceTheValue: Int) {
self.value = twiceTheValue / 2
self.twiceTheValue = twiceTheValue
}
然后compactMap
将支持此初始化,因为它期望闭包返回一个可选值,因此如果我们在调用中删除参数名称
let out7 = array.compactMap(TwoTimesInt.init)
将使用第二个init,而map
函数将以相同的方式使用第一个init方法。
let out8 = array.map(TwoTimesInt.init)