【问题标题】:In Swift, what's the difference between calling UINavigationController() vs UINavigationController.init()?在 Swift 中,调用 UINavigationController() 与 UINavigationController.init() 有什么区别?
【发布时间】:2016-11-20 23:31:51
【问题描述】:

在 Swift 中,调用 UINavigation()UINavigation.init() 有什么区别?他们似乎都返回了UINavigationController 的有效实例。

【问题讨论】:

    标签: swift swift3 ios10 xcode8.1


    【解决方案1】:

    UINavigationController()UINavigationController.init() 是完全相同的东西。您可以通过在 Playground 中输入两者然后单击 option 来验证这一点。两者都显示了相同初始化程序的文档。

    Swift 约定是只使用类型名称(不带.init)。

    【讨论】:

    • 在重写初始化程序时,您似乎需要明确调用init() 的唯一地方(据我所知)是super.init()...
    • @NicolasMiari 是一个很好的观点,但作为附录,可能值得注意的是,super 不是一种类型,而是用于访问超类方法和属性的特殊 Swift 前缀(不仅仅是@ 987654328@)。它的用例和访问更类似于类型的实例,而不是类型本身(特别是超类的初始化器除外)。
    • 确实和Classname.init()不一样
    • 澄清一下——您可以省略.init 以调用初始化程序的唯一地方是当您按名称指定类型时(尽管这是大多数情况)。所有其他情况都需要使用.init 才能访问初始化程序(例如,type(of: someValue).init())。语言指南的相关部分is here btw (under "Initializer Expression").
    【解决方案2】:

    对于某些给定类型(例如UINavigationController),调用UINavigationController()UINavigationController.init()之间没有区别,但后一种语法可以(没有()调用)在我们想要使用闭包(或对闭包的引用)的上下文中引用某个给定类型的初始化器时很有用,比如Foo

    • 零个或多个参数,并且
    • 返回类型Foo,

    例如,(Int, Double) -> Foo。在这些情况下,使用语法Foo.init 可能会被证明是有用的:与其明确地让闭包重复调用一个已知的初始化器(将闭包的参数传递给初始化器),我们可以使用(参考)初始化器直接作为闭包。如果 Foo 的初始化程序的参数没有歧义,则在某些给定的闭包类型上下文中对 Foo.init 的引用将使用类型推断解析为正确的初始化程序。

    例如,考虑以下示例

    struct Foo {
        let foo: Int
    
        // (Int) -> Foo
        init(foo: Int) {
            self.foo = 2*foo
        }
    
        // (Int, Int) -> Foo
        init(foo: Int, bar: Int) {
            self.foo = foo + bar
        }
    
        // () -> Foo
        init() {
            self.foo = 42
        }
    }
    
    let arr = [1, 2, 3]
    let fooArr1 = arr.map { Foo(foo: $0) }
    let fooArr2 = arr.map(Foo.init)
                     /* map operation expects a single argument of type (Int) -> Foo, 
                        which we generally supply as a trailing closure. In this context,
                        Swift can, without ambiguity (since we have none, is this example), 
                        find the correct overload among the initializers of Foo */
    print(fooArr1.map { $0.foo }, fooArr2.map { $0.foo }) // [2, 4, 6] [2, 4, 6]
    
    let emptyTupArr = [(), (), ()]
    let fooArr3 = emptyTupArr.map(Foo.init) // inferred to be the '() -> Foo' initializer
    print(fooArr3.map { $0.foo }) // [42, 42, 42]
    

    【讨论】:

      【解决方案3】:

      从 Apple 文档中,您在子类化控制器时使用 init。看起来没有将值传递给单元函数,它只是返回一个标准的 UINavigationController

      https://developer.apple.com/reference/uikit/uinavigationcontroller

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-01-28
        • 2014-10-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-10
        • 2013-09-01
        • 2018-12-01
        相关资源
        最近更新 更多