init的目的是什么!可用的初始化程序?

时间:2014-11-24 15:20:26

标签: ios swift initialization optional

Apple Swift编程语言指南提到了init的存在!初始化程序,但没有提供任何示例。 (搜索init!in this page

我理解使用用init?声明的普通可用初始化程序,但是我没有得到这个其他版本的需要。需要什么?有人可以提供一个例子吗?

6 个答案:

答案 0 :(得分:2)

这有两个目的:

  • 导入Swift不知道的Cocoa API时。如果Swift不知道初始化程序是否可以返回nil,则用它来注释它!所以开发人员知道那里可能有一个零隐藏,如果实际上没有理由,就不会强迫开发人员测试nil。

  • 出于同样的原因,在其他情况下使用隐式解包的选项(您可能愿意在某些情况下交换编译时安全性以增加便利性。)

答案 1 :(得分:1)

我相信它与选项中的!绝对相同。 init?将返回一个可选项。 init!将返回一个隐式解包的可选项。

调用Obj-C API需要隐式解包的选项,您不确定它是否可以返回可选项。因此,您使用隐式展开的可选项,它的行为类似于非可选类型,但如果返回可选项,它将崩溃。

请注意,当引入Swift时,大多数Obj-C框架仅返回隐式解包的选项,但目前很多都返回选项或非可选类型,因为Apple正在查看代码并检查它们是否可以返回可选项。在Apple尚未正确标记初始化程序的任何地方都需要init!

答案 2 :(得分:1)

好问题Matteo,我正在为同样的问题寻找答案,因为 init!没有意义(如果它总是初始化一个对象,我们不需要可选),但我没有没有找到任何明确的答案。

我认为这是因为Apple还没有完成他的工作:“ ...自己的Objective-C类,以及尚未审核的框架中的类,初始化器被导入为 init ! ......

或许可以帮助你,“与Objective-C API交互”(Apple)中的文字

  • “在Objective-C中,初始化程序直接返回它们的对象 初始化。要在初始化失败时通知调用者,a Objective-C初始值设定项可以返回nil。在Swift中,这种模式是 内置于称为可用初始化的语言功能。许多 iOS和OS X系统框架中的Objective-C初始化程序已经存在 审计以指示初始化是否可能失败。这些 Objective-C初始化程序作为init(...)导入 - 如果 初始化不能失败 - 或初始化?(...)如果初始化可能失败。 在您自己的Objective-C类中,以及具有的框架中的类 尚未审核,初始化程序作为init导入!(...)。对于 例如,NSString(contentsOfFile :)初始化程序可能无法执行 如果文件不存在,则初始化NSString对象 提供的路径。您可以使用可选绑定来打开结果 如果初始化成功,则可以使用初始化程序。“

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithObjective-CAPIs.html

答案 3 :(得分:1)

即使这个问题已经存在了一段时间,我也会尝试一下,因为我认为一些示例源代码对于理解init!的用途是有用的(至少它是对我来说。)

隐式展开的可选项提供了两个有价值的东西:

  1. 为程序员带来便利(因此您不必在可选变量的末尾键入' ?')
  2. 运行时效率,因为它允许您只测试一次nil的可选项,然后(只要它是非nil)使用其未包装(即直接)值。
  3. 重要的一点是隐式展开的可选项是可选的,这意味着可以对nil进行测试。

    现在,关于init! - 可用的初始化程序的实用程序,我们可以使用它来获取上面列出的两个内容(方便性和运行时效率),同时仍然允许init函数失败(即返回nil)。正如其他人所说,这可以通过调用Objective-C API来实现,但它也可以直接从您可能选择编写的代码中发生。这是一个例子:

    class A {
        init!() {
            return nil  // something happens that causes init to fail
        }
    }
    
    var a:A! = A()      // variable 'a' *is* an optional, and also nil
    
    if a != nil {       // and we can test it!
        print( "a is not nil" )
    } else {
        print( "a is nil, better not use it." )
    }
    

    在这个例子中,我给自己一种方法来使class A的初始化失败,是的,可以用init?方法轻松完成它,但是当我创建一个类型为{的对象时{1}}我可能只需要测试初始化​​成功或失败一次 - 毕竟,我要么创建了A,要么我没有 - 并且之后如果它不是A我只想使用直接值。所以在这种情况下,使用nil - 可用的初始化器非常方便。

答案 4 :(得分:1)

它在两种情况下有所不同:

如果你写

let x: myclass = myclass(...)

然后初始化?因为init会不会编译?返回一个可选的;在里面!如果init方法返回nil,将编译但崩溃。

如果你写

let x = myclass(...)

然后它将在任何一种情况下编译,并且在任何一种情况下都不会崩溃。区别在于,在一种情况下,x具有myclass类型?而在另一种情况下键入myclass!行为明显不同。

如果您写下以下两种之一:

let x: myclass? = myclass(...)
let x: myclass! = myclass(...)

然后init是否无关紧要!或者初始化?使用了,因为任何一个都可以分配给一个可选的而不会崩溃。

答案 5 :(得分:-3)

init初始化程序与其他语言中的类的构造函数相同。 它设置初始值并执行一些初始操作(比如检查值是否大等)。 有意思:它也需要参数并且可以重载。

示例:

struct Celsius {
    var temperatureInCelsius: Double
    init(fromFahrenheit fahrenheit: Double) {
        temperatureInCelsius = (fahrenheit - 32.0) / 1.8
    }
    init(fromKelvin kelvin: Double) {
        temperatureInCelsius = kelvin - 273.15
    }
}
let boilingPointOfWater = Celsius(fromFahrenheit: 212.0)
let freezingPointOfWater = Celsius(fromKelvin: 273.15)

因此,当您调用struct时,它会根据您的调用参数返回不同的值。

了解更多信息:http://www.informit.com/articles/article.aspx?p=2246797