爲什麼要創建“隱式展開的可選項”,因爲這意味着您知道存在價值?

本文翻譯自: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 ...然後躺在這裏 龍

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