使用init作为结束符

时间:2019-08-08 10:50:27

标签: ios swift closures init

最近我在一本书中看到了以下代码行(关于CoreData)

return modelURLs(in: modelName).compactMap(NSManagedObjectModel.init)

我知道代码的作用,但问题是:为什么以及如何工作? 应该有一个闭包作为compactMap函数的参数,但是在 NORMAL 括号中只有一个“ NSManagedObjectModel.init”。这有什么秘诀?在那里做什么?如果有一个称为init的静态/类属性,它返回一个闭包,但我认为不存在,那么我会理解。

不幸的是,这本书没有更多地介绍这一行代码。我想从Apple文档中进一步阅读,但找不到任何内容。当我在Google上搜索“对闭包进行初始化”时,没有得到有用的结果。

所以你们是我最后的希望:)

顺便说一句:modelURLs(in:modelName)函数返回一个URL数组,但这在这里并不是很重要。

1 个答案:

答案 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)