为什么要创建“隐式展开的可选项”,因为这意味着您知道存在价值?

本文翻译自:Why create “Implicitly Unwrapped Optionals”, since that implies you know there's a value?

Why would you create a "Implicitly Unwrapped Optional" vs creating just a regular variable or constant? 为什么只创建一个正则变量或常量,而不是创建“隐式展开的可选”? If you know that it can be successfully unwrapped then why create an optional in the first place? 如果您知道可以成功解包,那么为什么首先要创建一个可选的? For example, why is this: 例如,为什么这样:

let someString: String! = "this is the string"

going to be more useful than: 比以下内容更有用:

let someString: String = "this is the string"

If ”optionals indicate that a constant or variable is allowed to have 'no value'”, but “sometimes it is clear from a program's structure that an optional will always have a value after that value is first set”, what is the point of making it an optional in the first place? 如果“可选参数指示允许常量或变量具有'无值'”,但“有时从程序的结构中可以看出,可选参数在首次设置该值后将始终具有一个值”,这是什么意思呢?首先使它成为可选项? If you know an optional is always going to have a value, doesn't that make it not optional? 如果您知道可选值总是会有一个值,那不是使它成为非可选值吗?


#1楼

参考:https://stackoom.com/question/1cjJH/为什么要创建-隐式展开的可选项-因为这意味着您知道存在价值


#2楼

Consider the case of an object that may have nil properties while it's being constructed and configured, but is immutable and non-nil afterwards (NSImage is often treated this way, though in its case it's still useful to mutate sometimes). 考虑一个对象的情况,该对象在构造和配置时可能具有nil属性,但是此后是不可变的且非nil(NSImage通常以这种方式处理,尽管在这种情况下,有时进行突变仍然很有用)。 Implicitly unwrapped optionals would clean up its code a good deal, with relatively low loss of safety (as long as the one guarantee held, it would be safe). 隐式解开的可选对象将清理其代码,并且安全损失相对较低(只要持有一个保证,它将是安全的)。

(Edit) To be clear though: regular optionals are nearly always preferable. (编辑)但是要明确:常规的可选几乎总是首选。


#3楼

One-line (or several-line) simple examples don't cover the behavior of optionals very well — yeah, if you declare a variable and provide it with a value right away, there's no point in an optional. 单行(或多行)的简单示例不能很好地说明可选变量的行为-是的,如果您声明一个变量并立即为其提供值,那么可选变量毫无意义。

The best case I've seen so far is setup that happens after object initialization, followed by use that's "guaranteed" to follow that setup, eg in a view controller: 到目前为止,我所见过的最好的情况是在对象初始化之后进行设置,然后“保证”使用它来遵循该设置,例如在视图控制器中:

class MyViewController: UIViewController {

    var screenSize: CGSize?

    override func viewDidLoad {
        super.viewDidLoad()
        screenSize = view.frame.size
    }

    @IBAction printSize(sender: UIButton) {
        println("Screen size: \(screenSize!)")
    }
}

We know printSize will be called after the view is loaded — it's an action method hooked up to a control inside that view, and we made sure not to call it otherwise. 我们知道在视图加载后将调用printSize -这是连接到该视图内的控件的action方法,我们确保不要以其他方式调用它。 So we can save ourselves some optional-checking/binding with the ! 因此,我们可以使用来节省一些可选的检查/绑定! . Swift can't recognize that guarantee (at least until Apple solves the halting problem), so you tell the compiler it exists. Swift无法识别这种保证(至少在苹果公司解决暂停问题之前),因此您告诉编译器它存在。

This breaks type safety to some degree, though. 但是,这在某种程度上破坏了类型安全性。 Anyplace you have an implicitly unwrapped optional is a place your app can crash if your "guarantee" doesn't always hold, so it's a feature to use sparingly. 如果您的“担保”并不总是成立,则在任何具有隐式解包的可选内容的地方,应用程序都可能崩溃,因此该功能可少量使用。 Besides, using ! 此外,使用! all the time makes it sound like you're yelling, and nobody likes that. 无时无刻都听起来像是在大吼大叫,没人喜欢。


#4楼

Implicitly unwrapped optionals are useful for presenting a property as non-optional when really it needs to be optional under the covers. 隐式解开的可选选项对于在确实需要掩盖属性时将其表示为非可选属性很有用。 This is often necessary for "tying the knot" between two related objects that each need a reference to the other. 这对于在每个需要相互引用的两个相关对象之间“打结”通常是必需的。 It makes sense when neither reference is actually optional, but one of them needs to be nil while the pair is being initialized. 当两个引用实际上都不是可选的,但在初始化该对时其中一个需要为零时,这是有道理的。

For example: 例如:

// These classes are buddies that never go anywhere without each other
class B {
    var name : String
    weak var myBuddyA : A!
    init(name : String) {
        self.name = name
    }
}

class A {
    var name : String
    var myBuddyB : B
    init(name : String) {
        self.name = name
        myBuddyB = B(name:"\(name)'s buddy B")
        myBuddyB.myBuddyA = self
    }
}

var a = A(name:"Big A")
println(a.myBuddyB.name)   // prints "Big A's buddy B"

Any B instance should always have a valid myBuddyA reference, so we don't want to make the user treat it as optional, but we need it to be optional so that we can construct a B before we have an A to refer to. 任何B实例都应始终具有有效的myBuddyA引用,因此我们不想让用户将其视为可选,但是我们需要将其视为可选,以便我们可以在引用A之前构造B

HOWEVER! 然而! This sort of mutual reference requirement is often an indication of tight coupling and poor design. 这种相互参考的要求通常表示紧密耦合和不良设计。 If you find yourself relying on implicitly unwrapped optionals you should probably consider refactoring to eliminate the cross-dependencies. 如果发现自己依赖于隐式展开的可选对象,则可能应该考虑进行重构以消除交叉依赖关系。


#5楼

The rationale of implicit optionals is easier to explain by first looking at the rationale for forced unwrapping. 隐式可选的基本原理更容易通过首先查看强制展开的基本原理来解释。

Forced unwrapping of an optional (implicit or not), using the ! 使用!强制展开可选(隐式或非隐式)的包装 operator, means you're certain that your code has no bugs and the optional already has a value where it is being unwrapped. 运算符,意味着您可以确定您的代码没有错误,并且可选代码在解包时已经具有一个值。 Without the ! 没有! operator, you would probably just assert with an optional binding: 运算符,您可能只需声明一个可选绑定即可:

 if let value = optionalWhichTotallyHasAValue {
     println("\(value)")
 } else {
     assert(false)
 }

which is not as nice as 不如

println("\(value!)")

Now, implicit optionals let you express having an optional which you expect to always to have a value when unwrapped, in all possible flows. 现在,隐式可选选项使您可以表示具有一个可选选项,该选项在展开时在所有可能的流中都希望始终具有一个值。 So it just goes a step further in helping you - by relaxing the requirement of writing the ! 因此,通过放宽编写!的要求,它为您提供了进一步的帮助! to unwrap each time, and ensuring that the runtime will still error in case your assumptions about the flow are wrong. 每次解包,并确保在您对流的假设错误的情况下,运行时仍会出错。


#6楼

Implicitly unwrapped optionals are pragmatic compromise to make the work in hybrid environment that has to interoperate with existing Cocoa frameworks and their conventions more pleasant, while also allowing for stepwise migration into safer programing paradigm — without null pointers — enforced by the Swift compiler. 隐式展开的可选选项是实用的折衷方案,它使必须与现有Cocoa框架及其约定互操作的混合环境中的工作更加愉快,同时还允许逐步移植到Swift编译器强制执行的更安全的编程范例(无空指针)中。

Swift book, in The Basics chapter, section Implicitly Unwrapped Optionals says: 一本Swift书,在“基础知识”一章的“ 隐式解开可选内容部分中说:

Implicitly unwrapped optionals are useful when an optional's value is confirmed to exist immediately after the optional is first defined and can definitely be assumed to exist at every point thereafter. 当在第一个定义了可选对象的值之后立即确认该可选对象的值存在并且可以肯定地假定此后的每个点都存在时,隐式解开的可选对象很有用。 The primary use of implicitly unwrapped optionals in Swift is during class initialization, as described in Unowned References and Implicitly Unwrapped Optional Properties . Swift中隐式解包的可选对象的主要用途是在类初始化期间,如无主引用和隐式解开的可选属性中所述

You can think of an implicitly unwrapped optional as giving permission for the optional to be unwrapped automatically whenever it is used. 您可以将隐式解压缩的可选内容视为允许使用该可选内容以使其自动解包的权限。 Rather than placing an exclamation mark after the optional's name each time you use it, you place an exclamation mark after the optional's type when you declare it. 不必在每次使用可选名称时都在其名称后放置一个感叹号,而是在声明它时在其可选类型后放置一个感叹号。

This comes down to use cases where the non- nil -ness of properties is established via usage convention, and can not be enforced by compiler during the class initialization. 这归结到使用情况下, nil通过使用约定建成的酒店-ness,并且不能由编译器类的初始化过程中强制执行。 For example, the UIViewController properties that are initialized from NIBs or Storyboards, where the initialization is split into separate phases, but after the viewDidLoad() you can assume that properties generally exist. 例如,从NIB或Storyboards初始化的UIViewController属性,其中将初始化分为多个阶段,但是在viewDidLoad()之后,您可以假定属性通常存在。 Otherwise, in order to satisfy the compiler, you had to be using the forced unwrapping , optional binding or optional chaining only to obscure the main purpose of the code. 否则,为了使编译器满意,您必须仅使用强制解包可选绑定可选链接来掩盖代码的主要用途。

Above part from the Swift book refers also to the Automatic Reference Counting chapter : Swift书的上方部分还涉及“ 自动引用计数”一章

However, there is a third scenario, in which both properties should always have a value, and neither property should ever be nil once initialization is complete. 但是,存在第三种情况,其中两个属性都应始终具有值,并且初始化完成后,两个属性都不应nil In this scenario, it is useful to combine an unowned property on one class with an implicitly unwrapped optional property on the other class. 在这种情况下,将一个类上的未拥有属性与另一类上的隐式展开的可选属性结合起来很有用。

This enables both properties to be accessed directly (without optional unwrapping) once initialization is complete, while still avoiding a reference cycle. 这样,初始化完成后就可以直接访问这两个属性(没有可选的展开),同时仍然避免了引用周期。

This comes down to the quirks of not being a garbage collected language, therefore the breaking of retain cycles is on you as a programmer and implicitly unwrapped optionals are a tool to hide this quirk. 这归结为不是垃圾收集语言的怪癖,因此,作为程序员,保留周期的中断就在您身旁,而隐式展开的可选变量则是隐藏此怪癖的工具。

That covers the “When to use implicitly unwrapped optionals in your code?” question. 涵盖了“何时在代码中使用隐式解开的可选内容?”问题。 As an application developer, you'll mostly encounter them in method signatures of libraries written in Objective-C, which doesn't have the ability to express optional types. 作为应用程序开发人员,您将在用Objective-C编写的库的方法签名中经常遇到它们,它们没有表达可选类型的能力。

From Using Swift with Cocoa and Objective-C, section Working with nil : 从结合使用Swift和Cocoa和Objective-C中, 使用nil部分

Because Objective-C does not make any guarantees that an object is non-nil, Swift makes all classes in argument types and return types optional in imported Objective-C APIs. 因为Objective-C不能保证对象不是nil,所以Swift使所有类型的参数类型和返回类型在导入的Objective-C API中都是可选的。 Before you use an Objective-C object, you should check to ensure that it is not missing. 在使用Objective-C对象之前,应检查以确保没有丢失它。

In some cases, you might be absolutely certain that an Objective-C method or property never returns a nil object reference. 在某些情况下,您可以绝对确定Objective-C方法或属性从不返回nil对象引用。 To make objects in this special scenario more convenient to work with, Swift imports object types as implicitly unwrapped optionals . 为了使在这种特殊情况下的对象更易于使用,Swift将对象类型作为隐式解包的optional导入。 Implicitly unwrapped optional types include all of the safety features of optional types. 隐式展开的可选类型包括可选类型的所有安全功能。 In addition, you can access the value directly without checking for nil or unwrapping it yourself. 此外,您可以直接访问该值,而无需自己检查nil或将其解包。 When you access the value in this kind of optional type without safely unwrapping it first, the implicitly unwrapped optional checks whether the value is missing. 当您访问这种可选类型的值而没有首先安全地对其进行拆包时,隐式解包的可选包会检查该值是否丢失。 If the value is missing, a runtime error occurs. 如果缺少该值,则会发生运行时错误。 As a result, you should always check and unwrap an implicitly unwrapped optional yourself, unless you are sure that the value cannot be missing. 因此,除非您确定该值不会丢失,否则您应该始终自己检查并解开一个隐式解包的可选内容。

...and beyond here lay ...然后躺在这里 龙

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章