モバイル開発の経験(Swiftの使用を含む)にもかかわらず、Swiftのオプションに基づいて何をすべきかを定期的に知っていましたが、 なぜそうなのか明確に理解できませんでした。 気を散らし、ドキュメントを掘り下げなければなりませんでした-「限界ノート」の数は、憂鬱な周期性で補充されました。 ある時点で、彼らは大衆に達し、私はそれらを単一の包括的なガイドにまとめることにしました。 可能な限り詳細にトピックを開示する試みが行われたため、資料は非常に膨大であることが判明しました。 この記事は、Swiftの初心者開発者とObjective-Cの世界の経験豊富な専門家の両方に役立ちます。Objective-Cの世界では、Objective-Cが新しい何かを見つける可能性がゼロではありません。 そして、それが見つからない場合は、コメントに独自の新しいものを追加し、誰もが利益を得ます。
オプションとは何ですか?
オプションは、変数の値が存在しない状況を処理するための便利なメカニズムです。 値は、使用されている場合にのみ使用されます。
nilのチェックがあるときにオプションが必要なのはなぜですか?
まず、 nil
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    等価性/不等価性チェックは、 null許容型にのみ適用され、プリミティブ型、構造体、および列挙には適用されません。 プリミティブ型の変数に値がないことを示すには、 NSNotFoundなどの特別な値を入力する必要があります。 
NSNotFoundは、特別な値と見なされる必要があるだけでなく、変数の有効な値のセットに入らないようにするためにも必要です。 NSNotFoundがNSIntegerMaxと等しいと見なされるという事実により、状況は複雑になります。 プラットフォーム(32ビット/ 64ビット)によって意味が異なる場合があります。 これは、 NSNotFoundをファイルやアーカイブに直接書き込むことも、 分散オブジェクトで使用することもできないことを意味します。
したがって、この変数のユーザーは、特別な値が可能なことを考慮する必要があります。 Swiftでは、プリミティブ型でもオプションのスタイルで使用できます。つまり、値がない可能性があることを明示的に示します。
 第二に、コンパイル段階で明示的なオプションがチェックされるため、実行時のエラーの数が減ります。  Swiftのオプション変数は、オプション変数と同じ方法で使用することはできません(暗黙的に取得されたオプションを除き、詳細については暗黙的なアンラッピングを参照してください )。 オプションを強制的に通常の値に変換するか、 if let
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     、 guard let
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    および??
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    などの特別な変換イディオムを使用する必要があります。  。  Swiftのオプションは、検証だけでなく、 型 理論の オプション型のパラダイム全体を実装します。 
 第三に、オプションはnil
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    チェックよりも構文的に簡潔です。これは、オプションの呼び出しチェーン、いわゆるOptional Chainingで特に顕著です。 
どのように機能しますか?
  Swiftのオプションは、 nil
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    または特定のタイプのオブジェクトを含むことができる特別なコンテナオブジェクトです。このオブジェクトは、このコンテナが宣言されたときに指定されます。 これらの2つの状態は、それぞれ用語NoneおよびSomeで示されます。 オプション変数の作成中に割り当てられた値が指定されていない場合、デフォルトでnil
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    割り当てられます。 
ドキュメントでは、明示的な割り当てがない場合のデフォルト値は言及されていませんが、オプションはラップされた値またはnil(valueがない場合)を表す と言われています。 オプション変数が明示的な割り当てなしで宣言された場合(一部は割り当てられなかったものもあります)、論理的にはNoneが暗黙的に割り当てられます-オプションには3番目の「初期化されていない」状態はありません。
 タイプ名とトークンの組み合わせでオプションが宣言されています?
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      。 エントリはInt?
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      -これはコンテナ宣言であり、そのインスタンスには内部nil
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     (状態None Int )またはタイプInt
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     (状態Some Int )の値が含まれる場合があります。 それがInt?
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    変換するときの理由Int?
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      Int
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    では、 castの代わりにunwrappingという用語を使用します。 オプションの「コンテナ」の本質を強調しています。  Swift nil
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    トークンは、任意のオプションに割り当てることができるNone状態を示します。 これにより、論理的に、オプションではない変数にnil
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     (状態None )を割り当てることができなくなります。 
実際、オプションはシステム列挙です:
 public enum Optional<Wrapped> : ExpressibleByNilLiteral { /// The absence of a value. /// /// In code, the absence of a value is typically written using the `nil` /// literal rather than the explicit `.none` enumeration case. case none /// The presence of a value, stored as `Wrapped`. case some(Wrapped) /// Creates an instance that stores the given value. public init(_ some: Wrapped) ... /// Creates an instance initialized with `nil`. /// /// Do not call this initializer directly. It is used by the compiler // when you initialize an `Optional` instance with a `nil` literal. public init(nilLiteral: ()) ... }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
        Optional
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    列挙には、 .none
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    とsome(Wrapped)
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     2つの状態があります。 レコードがWrapped?
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     プリプロセッサ( Swiftの型システム )によって処理され、 Optional<Wrapped>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    変換されます。 次のエントリは同等です。 
 var my_variable: Int?
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
       var my_variable: Optional<Int>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
       実際、 nil
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    トークンはOptional.none
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     、つまり 次のエントリは同等です。 
 var my_variable: Int? = nil
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
       var my_variable: Optional<Int> = Optional.none
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
       var my_variable = Optional<Int>.none
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
        Optional
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    列挙には、2つのコンストラクターがあります。 最初のコンストラクタinit(_ some: Wrapped)
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    は、対応する型の値を入力として受け入れます。 次のエントリは同等です。 
 var my_variable = Optional(42) //  .some- Int  
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
       var my_variable = Optional<Int>(42) //    Int  
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
       var my_variable = Int?(42) //  Int   
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
       var my_variable: Int? = 42 //  Int   
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
       var my_variable = Optional.some(42) //  Int  
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
       var my_variable = Optional<Int>.some(42) //     
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
        2番目のコンストラクタinit(nilLiteral: ())
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    は、 ExpressibleByNilLiteral
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    プロトコルの実装です 
 public protocol ExpressibleByNilLiteral { /// Creates an instance initialized with `nil`. public init(nilLiteral: ()) }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
       オプションの変数を状態.none
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    で初期化します。 このコンストラクターはコンパイラーによって使用されます。  ドキュメントによると、直接呼び出すことは推奨されていません 
 var test = Optional<Int>(nilLiteral: ()) //  
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
       空のVoid ()
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    タプルをnil
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    変換することnil
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    いくぶん明白でnil
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    ないため、これは論理的です。 
代わりにこのコンストラクタを使用してください
 var my_variable: Int? = nil //  var my_variable: Int? = Optional.none
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
      または明示的な割り当てをまったく使用しない
 var my_variable: Int?
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
       デフォルトではnil
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    が割り当てられるためです。 
  Optional<Wrapped>
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    列挙には、unsafelyUnwrappedプロパティも含まれます。このプロパティは、オプションのオプションの.some
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    への読み取りアクセスを提供.some
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    ます。 
 public enum Optional<Wrapped> : ExpressibleByNilLiteral { ... /// The wrapped value of this instance, unwrapped without checking whether /// the instance is `nil`. public var unsafelyUnwrapped: Wrapped { get } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
       オプションが.none
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    状態の場合、 .none
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    にアクセスすると、プログラムが深刻にクラッシュします。 
デバッグモードデバッグビルド-なしでは、ランタイムエラーが発生します。
 _fatal error: unsafelyUnwrapped of nil optional_
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
       リリースビルドで最適化されたビルド-Oでは 、ランタイムエラーまたは未定義の動作が発生します。 より安全な操作はForce Unwrapping (またはExplicit Unwrapping ) !
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    トークンで示される.some
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    値.some
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    抽出を.some
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    します!
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      。  Force Unwrappingを.none
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    状態のオプションに適用すると、ランタイムエラーが発生します。 
 _fatal error: unexpectedly found nil while unwrapping an Optional value_
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       let my_variable1 = Int?(42) //  42,  Optional Int let my_value1A = my_variable1! //  42,  Int let my_value1B = my_variable1.unsafelyUnwrapped //  42,  Int let my_variable2 = Int?.none //  nil,  Optional Int let my_value2A = my_variable2! //   //     -Onone,     -O let my_value2B = my_variable2.unsafelyUnwrapped
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
      使用のイディオム
 通常の2状態の列挙を使用することはほとんど意味がありません。 同様のメカニズムを自分で実装することは非常に可能です:対応する値の2つの状態とコンストラクターを使用して列挙型を作成し、 Force Unwrappingの接尾辞演算子を追加し(たとえば、 ここで行われます )、 nil
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    と比較する機能を追加するか、独自のnil
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    とtを作成します.d。 オプションは、その使用が外国ではなく自然であるように、言語自体に直接統合する必要があります。 もちろん、このような統合は「シンタックスシュガー」と見なすことができますが、その上にコードを記述(および読み取り)するための高レベル言語は簡単で快適でした。  Swiftでオプションを使用するには、エラーを減らし、コードをより簡潔にするために、いくつかのイディオムまたは特別な言語構成が必要です。 そのようなイディオムには、 暗黙的なアンラッピング 、 オプションのチェーン 、 Nil-Coalescing、およびオプションのバインディングが含まれます。 
暗黙的なアンラッピング
  Force Unwrappingを安全に使用するには、たとえばif条件でnil
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    を事前に確認する必要があります。 
 // getOptionalResult()   nil let my_variable: Int? = getOptionalResult() //  Optional Int if my_variable != nil { // my_value  .some-   getOptionalResult() let my_value = my_variable! } else { //   let my_value = my_variable! }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
       プログラムの構造から、変数は技術的にはオプションであることが明らかな場合もありますが、最初の使用時には常に.some
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    状態になっています。  nil
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    はありません。 オプションを非オプションのコンテキストで使用するには(たとえば、オプションの型のパラメーターを使用して関数に渡す)、退屈で面倒な事前チェックでForce Unwrappingを常に使用する必要があります。 これらの場合、暗黙的な取得オプション-Implicitly Unwrapped Optionalを使用できます。 暗黙的な検索オプションは、タイプ名とトークンの組み合わせで宣言されます!
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      : 
 let my_variable1: Int? = 42 //  Optional Int let my_variable2: Int! = 42 //  Implicitly Unwrapped Optional Int var my_variable3: Int! = 42 //  Implicitly Unwrapped Optional Int ... my_variable3 = nil // -   nil ... func sayHello(times:Int) { for _ in 0...times { print("Hello!") } } sayHello(times: my_variable1!) //     sayHello(times: my_variable1) //   sayHello(times: my_variable2!) // ,       sayHello(times: my_variable2) //   sayHello(times: my_variable3) //  
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
        sayHello(times: my_variable2)
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    への呼び出しでは、 my_variable2
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    からの値42
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    抽出は暗黙的にのみ実行されます。 暗黙的に取得されたオプションを使用すると、コードが読みやすくなります-気を散らす感嘆符はありません(おそらく、読者は最初にチェックせずにForce Unwrappingを使用することを心配するでしょう)。 実際には、エラーの可能性を高めるアンチパターンです。 暗黙的に取得されたオプションは、オプションのコンテキストでオプションが使用されているという事実にコンパイラーに「目を閉じさせる」ことを強制します。 コンパイル時に検出できるエラー( sayHello(times: my_variable1)
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    は実行時にのみ表示されます( sayHello(times: my_variable3)
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    呼び出す)。 明示的なコードは、暗黙的なコードよりも常に優れています。 感嘆符をなくすためだけでなく、このようなコードセキュリティの低下が必要であると想定するのは論理的です。 
 暗黙的に取得されたオプションを使用self
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    と、コンストラクターでself
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    を使用してプロパティを初期化すると同時に、次のことができます。 
-   2段階の初期化の規則に違反しないでください(コンストラクターでは、 self
 
 
 
 にアクセスする前にすべてのプロパティを初期化する必要があります)。そうでない場合、コードは単にコンパイルされません。
- 必要のないプロパティでは、過度のオプションを避けます(その意味では、プロパティの値をなくすことはできません)。
 コンストラクターでself
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    を使用してプロパティを初期化する良い例は、 ドキュメントに記載されています 。 
 class Country { let name: String var capitalCity: City! init(name: String, capitalName: String) { self.name = name self.capitalCity = City(name: capitalName, country: self) } } class City { let name: String unowned let country: Country init(name: String, country: Country) { self.name = name self.country = country } } var country = Country(name: "Canada", capitalName: "Ottawa") print("\(country.name)'s capital city is called \(country.capitalCity.name)") // Prints "Canada's capital city is called Ottawa"
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
       この例では、 CountryクラスとCityクラスのインスタンスには、初期化が完了するまでに相互にフレンドリンクが必要です。 各国には首都がなければならず、各首都には国がなければなりません。 これらの接続はオプションではなく、無条件です。  country
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    オブジェクトを初期化するプロセスでは、 capitalCity
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    プロパティを初期化する必要があります。  capitalCity
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    を初期化するには、 Cityクラスのインスタンスを作成する必要があります。  Cityコンストラクターには、対応するCountryインスタンスがパラメーターとして必要です。  self
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    へのアクセスが必要です。 問題は、 Countryインスタンスがまだ完全に初期化されていないことです。  self
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    は使用できません。 
 このタスクにはエレガントなソリューションがありますcapitalCity
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     、暗黙的に取得される可変オプションであるcapitalCity
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    宣言されています。 任意の可変オプションと同様に、 capitalCity
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    はデフォルトでnil
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    状態に初期化されます。つまり、 Cityコンストラクターが呼び出されるまでに、 country
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    オブジェクトのすべてのプロパティはすでに初期化されています。  2段階の初期化の要件が満たされ、 Countryコンストラクターは第2フェーズにありますself
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    をCityコンストラクターに渡すことができます。  capitalCity
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    は暗黙的なオプションです。 追加せずにオプションのコンテキストでアクセスできます!
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      。 
 暗黙的に取得されたオプションを使用することの副作用は、「組み込み」 assert
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    です。何らかの理由でcapitalCity
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    がnil
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    状態のままになると、ランタイムエラーとプログラムのクラッシュが発生します。 
 暗黙的に取得された@IBOutlet
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    の正当な使用のもう1つの例は@IBOutlet
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    命令です。その使用のコンテキストは、変数が最初の呼び出し時に.some
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    値を自動的に割り当てられることを意味します。 そうでない場合、実行時エラーが発生します。  Interface Builderの自動コード生成は、暗黙的な@IBOutlet
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    形式で@IBOutlet
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    してプロパティを作成し@IBOutlet
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     。 この動作が受け入れられない場合、 @IBOutlet
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    を持つプロパティを明示的なオプションとして宣言し、常に.none
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    値を明示的に処理.none
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    ます。 原則として、誤って@IBOutlet
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     -propertyが@IBOutlet
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    れた場合に長時間のデバッグを行うよりも、すぐに「フォール」を取得することをお@IBOutlet
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    ます。 
オプションの連鎖
  オプションのチェーンは、各リンクがオプションを返す連続したチェーン呼び出しのプロセスです。 プロセスは、 nil
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    状態にある最初のオプションで中断されます。この場合、呼び出しチェーン全体の結果もnil
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    ます。 チェーン内のすべてのリンクが.some
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    状態にある場合、結果の値は最後の呼び出しの結果ではオプションになります。 チェーンリンクの形成にトークンが使用されています?
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      、オプションを返す呼び出しの直後に配置されます。 チェーンリンクには、オプションを返す任意の操作を使用できます。ローカル変数へのアクセス(最初のリンクとして)、プロパティとメソッドの呼び出し、インデックスによるアクセス。 
  オプションのシェーニングは、常に左から右に順番に機能します。 次の.some
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    は前のリンクの値であり、チェーンの結果の値は常にオプションです。 チェーンは、次のルールに従って機能します。 
- 最初のリンクはオプションである必要があります。
-  トークンの後?
 
 
 
 次のリンクがあるはずです。
-  リンクが.none
 
 
 
 状態の場合、チェーンは呼び出しプロセスを中断し、nil
 
 
 
 を返します。
-  リンクが.some
 
 
 
 状態にある場合、チェーンは.some
 
 
 
 リンク.some
 
 
 
 を次のリンク(ある場合)に.some
 
 
 
 ます。
- 最後のリンクの結果がオプションの場合、チェーンはこのオプションを返します。
-  最後のリンクの結果がオプションでない場合、チェーンはこの結果を返し、オプションで「ラップ」します(計算の結果.some
 
 
 
 返されたオプションの.some
 
 
 
 割り当てられます)。
 //    :   —  `country.mainSeaport?`, country.mainSeaport?.nearestVacantPier?.capacity //  ,  `?`     let mainSeaport = country.mainSeaport? //   `nil`    country = Country(name: "Mongolia") let capacity = country.mainSeaport?.mainPier?.capacity //    —      country = Country(name: "Finland") let nearestVacantPier = country.mainSeaport?.nearestVacantPier //    —   ,   capacity //    country = Country(name: "Finland") let capacity = country.mainSeaport?.nearestVacantPier?.capacity
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
       オプションの呼び出しチェーンとネストされたオプションを区別することが重要です。 ネストされたオプションは.some
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    あるオプションの.some
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    が別のオプション.some
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    ある場合に形成されます。 
 let valueA = 42 let optionalValueA = Optional(valueA) let doubleOptionalValueA = Optional(optionalValueA) let tripleOptionalValueA = Optional(doubleOptionalValueA) let tripleOptionalValueB: Int??? = 42 //  `?`    let doubleOptionalValueB = tripleOptionalValueB! let optionalValueB = doubleOptionalValueB! let valueB = optionalValueB! print("\(valueA)") // 42 print("\(optionalValueA)") // Optional(42) print("\(doubleOptionalValueA)") // Optional(Optional(42)) print("\(tripleOptionalValueA)") // Optional(Optional(Optional(42))) print("\(tripleOptionalValueB)") // Optional(Optional(Optional(42))) print("\(doubleOptionalValueB)") // Optional(Optional(42)) print("\(optionalValueB)") // Optional(42) print("\(valueB)") // 42
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
        オプションのシェーニングでは、返されるオプションのネストレベルは増加しません。 それにもかかわらず、これは、リンクの結果の値がいくつかのレベルのネストを持つオプションである場合の状況を除外しません。 このような状況では、チェーンを継続するには登録する必要があります?
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     ネストレベルの数に等しい量: 
 let optionalAppDelegate = UIApplication.shared.delegate let doubleOptionalWindow = UIApplication.shared.delegate?.window let optionalFrame = UIApplication.shared.delegate?.window??.frame //  '?' print("\(optionalAppDelegate)") // Optional( ... ) print("\(doubleOptionalWindow)") // Optional(Optional( ... )) print("\(optionalFrame)") // Optional( ... )
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
       一般的に、トークンを使用してすべてのレベルのネストを「デプロイ」する必要はありません?
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     それらのいくつかは、強制抽出によって置き換えることができます!
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      、チェーン内の「暗黙的な」リンクの数を減らします。 別の質問は、これが理にかなっているかどうかです。 
  UIApplication.shared.delegate?.window??.frame
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    チェーンは、実際には4つのリンクで構成されています: UIApplication.shared.delegate?
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      .frame
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    と2つのリンクを1回の呼び出しで結合します。  。  2番目の「二重」リンクは、オプションのネストの2番目のレベルで表されます。 
 この例の重要な機能は、前の例のdoubleOptionalValue
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    の形成方法とは異なり、double optionalを形成する特別な方法でもあります。  UIApplication.shared.delegate!.window
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    は、オプションが返されるオプションのプロパティです。 プロパティのオプションとは、プロパティから返されるオプションの.some
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    だけでなく、プロパティ自体が存在しない可能性があることを意味します。 オプションのプロパティは、他のすべてのプロパティと同様に、オプションのプロパティだけでなく、任意のタイプを返すことができます。 この種のオプションは、 optional
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    修飾子を使用して@ objcプロトコルで形成されoptional
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     。 
 public protocol UIApplicationDelegate : NSObjectProtocol { ... @available(iOS 5.0, * ) optional public var window: UIWindow? { get set } //  optional ... }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
       オプションのプロパティとメソッド(それ以外の場合はオプションの要件)を備えたプロトコルでは、オプションの要件ごとおよびプロトコル自体に対して@objc
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    修飾子@objc
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    指定されます。 この要件は、上の例のUIApplicationDelegateプロトコルには適用されません。  Objective-CのシステムライブラリからSwiftに変換されます。 そのようなプロトコルを受け入れるオブジェクトで未実現のオプション要件を呼び出すと、対応するタイプのオプションが.none
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    状態で.none
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    ます。 実装されたオプション要求を呼び出すと、対応するタイプのオプションが.some
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    状態で.some
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    ます。 したがって、オプションのプロパティとメソッドは、 オプションのshainingとは対照的に、返されるオプションのネストレベルを増やします。 オプションのメソッドは、プロパティと同様に、オプションで完全に「ラップ」されます。メソッド全体は、戻り値だけでなく.some
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    値に配置されます。 
 @objc public protocol myOptionalProtocol { @objc optional var my_variable: Int { get } @objc optional var my_optionalVariableA: Int? { get } //  : //  @objc      Int?, .. Int //    @objc optional var my_optionalVariableB: UIView? { get } @objc optional func my_func() -> Int @objc optional func my_optionalResultfuncA() -> Int? //  : //  @objc      Int?, .. Int //    @objc optional func my_optionalResultfuncB() -> UIView? @objc optional init(value: Int) //  : //  optional    } @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate, myOptionalProtocol { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { let protocolAdoption = self as myOptionalProtocol // Optional<Int> print("\(type(of: protocolAdoption.my_variable))") // Optional<Optional<UIView>> print("\(type(of: protocolAdoption.my_optionalVariableB))") // Optional<() -> Int> print("\(type(of: protocolAdoption.my_func))") // Optional<Int> print("\(type(of: protocolAdoption.my_func?()))") // Optional<() -> Optional<UIView>> print("\(type(of: protocolAdoption.my_optionalResultfuncB))") // Optional<UIView> print("\(type(of: protocolAdoption.my_optionalResultfuncB?()))") return true } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
         @objc
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     -   ,   ,      Swift       Objective-C: 
-       ,    Objective-C,      @objc
 
 
 
 (.. );
-   optional
 
 
 
 -init
 
 
 
 ;
-  c     @objc
 
 
 
 — .
   Force Unwrapping            ,    Force Unwrapping       .none
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     . 
Nil-Coalescing
  Nil-Coalescing  .some
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     - ,     .some
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     ,    ,     .none
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     .  Nil-Coalescing  ,   if else
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     ,   ,     ?
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      : 
 let optionalText: String? = tryExtractText() //  let textA: String if optionalText != nil { textA = optionalText! } else { textA = "Extraction Error!" } //   ,    let textB = (optionalText != nil) ? optionalText! : "Extraction Error!" //     let textC = optionalText ?? "Extraction Error!"
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
               .some
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     -  .       : 
 let optionalText: String?? = tryExtractOptionalText() let a = optionalText ?? Optional("Extraction Error!")
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
      :
 let wayA: Int? = doSomething() let wayB: Int? = doNothing() let defaultWay: Int = ignoreEverything() let whatDo = wayA ?? wayB ?? defaultWay
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
      Optional Binding
 Optional Binding  ,    .some
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     -,   ,             ( ). Optional Binding     if
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     , while
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      guard
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     . 
Optional Binding , , .
 ,        ,         nil
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     ,     nil
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     .         if
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     ,       true ,  nil
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       false : 
 var my_optionalVariable: Int? = 42 //  , my_variable ""  .some- my_optionalVariable if let my_variable = my_optionalVariable { print("\(my_variable)") // 42 } my_optionalVariable = nil //  , my_variable   if let my_variable = my_optionalVariable { print("\(my_variable)") } else { print("Optional variable is nil!") // Optional variable is nil! }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
       ,     true ,           . - nil
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
            .some
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     -  .   true .some
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     -      ""    (      Optional Binding ). 
       if
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       true ,  ,    false      .   ,  ,       .some
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     -,    false (   .none
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     )   .       guard
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     : 
 let my_optionalVariable: Int? = extractOptionalValue() //   let my_variableA: Int if let value = my_optionalVariable { my_variableA = value } else { return } print(my_variableA + 1) //  guard let my_variableB = my_optionalVariable else { return } print(my_variableB + 1)
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
        Swift     (,      )     as
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     .  ,         (,  ),      as!
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     ,     as?
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      。      Force Unwrapping , ..         ,           nil
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     : 
 class Shape {} class Circle: Shape {} class Triangle: Shape {} let circle = Circle() let circleShape: Shape = Circle() let triangleShape: Shape = Triangle() circle as Shape //   42 as Float //   circleShape as Circle //   circleShape as! Circle // circle triangleShape as! Circle //   circleShape as? Circle // Optional<Circle> triangleShape as? Circle // nil
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
        ,    as?
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      ,       Optional Binding : 
 class Shape {} class Circle: Shape {} class Triangle: Shape {} let circleShape: Shape = Circle() let triangleShape: Shape = Triangle() //  ,   if let circle = circleShape as? Circle { print("Cast success: \(type(of: circle))") // Cast success: (Circle #1) } else { print("Cast failure") } //  ,    if let circle = triangleShape as? Circle { print("Cast success: \(type(of: circle))") } else { print("Cast failure") // Cast failure }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
      map flatMap
  map
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      flatMap
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
          Swift,        Optional : 
 public enum Optional<Wrapped> : ExpressibleByNilLiteral { ... /// Evaluates the given closure when this `Optional` instance is not `nil`, /// passing the unwrapped value as a parameter. /// /// Use the `map` method with a closure that returns a nonoptional value. public func map<U>(_ transform: (Wrapped) throws -> U) rethrows -> U? /// Evaluates the given closure when this `Optional` instance is not `nil`, /// passing the unwrapped value as a parameter. /// /// Use the `flatMap` method with a closure that returns an optional value. public func flatMap<U>(_ transform: (Wrapped) throws -> U?) rethrows -> U? ... }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
               .some
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     -      ,    .    nil
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     ,    nil
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     .   map
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      flatmap
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
        -:  flatMap
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
         nil
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     (),   map
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
         : 
 let my_variable: Int? = 4 let my_squareVariable = my_variable.map { v in return v * v } print("\(my_squareVariable)") // Optional(16) let my_reciprocalVariable: Double? = my_variable.flatMap { v in if v == 0 { return nil } return 1.0 / Double(v) } print("\(my_reciprocalVariable)") // Optional(0.25)
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
         map
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      flatmap
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       ,       if
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      guard
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     ,   ,      : 
 let dateFormatter = DateFormatter() dateFormatter.dateFormat = "dd MMM yyyy" let date: Date? = extractOptionalDate() //  let dateStringA: String if date != nil { dateStringA = dateFormatter.string(from: date!) } else { dateStringA = "Unknown date" } //   ,    let dateStringB = (date == nil ? nil : dateFormatter.string(from: date!)) ?? "Unknown date" // ,     ( map  ) let dateStringC = date.map(dateFormatter.string) ?? "Unknown date"
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
                   ,   .  ,         .some
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     -   ,   map
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      flatmap
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     : 
 //  Optional Binding        func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { if let cell = sender as? UITableViewCell, let indexPath = tableView.indexPathForCell(cell) { let item = items[indexPath.row] } } //    3 : // 1)     ; // 2)      flatMap  ; // 3) Optional Binding   flatMap. func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { if let indexPath = (sender as? UITableViewCell).flatMap(tableView.indexPathForCell) { let item = items[indexPath.row] } }
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
       func someThrowingFunction() throws -> Int { // ... } //  let y: Int? do { y = try someThrowingFunction() } catch { y = nil } //  let x = try? someThrowingFunction()
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
         x
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      y
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      ,   ,    someThrowingFunction()
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     .  ,    try?
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      ,     as?
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      。     try!
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     ,        .      ,    : 
 //  ,  loadImage    // photo    (   x  y) let photo = try! loadImage(atPath: "./Resources/John Appleseed.jpg")
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
      Objective-C
  Objective-C   .  nil
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      Objective-C   , ..          nil
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     .  Swift nil
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
         .none
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     ,      nil
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     ,   Xcode 6.3    Objective-C   Swift    .  Xcode 6.3  Objective-C          nullability annotations : 
 @interface myObject : NSObject @property (copy, readonly) NSArray * _Nullable myValuesA; @property (copy, readonly) NSString * _Nonnull myStringA; @property (copy, readonly, nullable) NSArray * myValuesB; @property (copy, readonly, nonnull) NSString * myStringB; @end
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
          nullable
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     ( _Nullable
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     ), nonnull
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     ( _Nonnull
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     ),   null_unspecified
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      null_resettable
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     . Nullability -a       ,       .        NS_ASSUME_NONNULL_BEGIN
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      NS_ASSUME_NONNULL_END
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
         .         ,        Objective-C (    , ,    nil
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
        nonnull ). 
Objective-C Swift :
-      NS_ASSUME_NONNULL_BEGIN
 
 
 
 NS_ASSUME_NONNULL_END
 
 
 
 () ;
-     nonnull
 
 
 
 _Nonnull
 
 
 
 () ;
-     nullable
 
 
 
 _Nullable
 
 
 
 ;
-     null_resettable
 
 
 
 ;
-    nullability -a   null_unspecified
 
 
 
 ( ) .
Swift Objective-C :
-      .none
 
 
 
 , NSNull ;
-      .some
 
 
 
 ,.some
 
 
 
 -.
,
  !
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
          ,   : 
- ;
- ;
-        as!
 
 
 
 ;
-        try!
 
 
 
 。
単項論理否定演算子は!
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    、異なるコンテキストを参照するため、考慮されません。
  ?
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
          ,   : 
- ;
- optional chaining ;
-        as?
 
 
 
 ;
-      nil
 
 
 
 try?
 
 
 
 。
三項条件演算子は?
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    、異なるコンテキストを参照するため、考慮されません。
  ??
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
          : 
- Optional haining ;
- Nil-Coalescing .
おわりに
, . ++ Java "", . "" , , "" . , .. , Cogito, ergo sum (. — ", "). , . Swift .
追加資料
- Generic Enumeration: Optional (developer.apple.com)
- Instance Property: unsafelyUnwrapped (developer.apple.com)
- Swift Language Guide: Optionals (developer.apple.com)
- Unowned References and Implicitly Unwrapped Optional Properties (developer.apple.com)
- Nil-Coalescing Operator (developer.apple.com)
- Optional Chaining (developer.apple.com)
- Optional Protocol Requirements (developer.apple.com)
- The as! Operator (developer.apple.com)
- Converting Errors to Optional Values (developer.apple.com)
- Nullability and Objective-C (developer.apple.com)
- Nullability and Optionals (developer.apple.com)
- Xcode 6.3 Release Notes: Objective-C Language Enhancements (developer.apple.com)
- Option type (en.wikipedia.org)
- Nullable type (en.wikipedia.org)
- Re-implementing Optionals using Swift's powerful enum type (jamesonquave.com)
 UPD: (by Alexander Zimin)  init(nilLiteral: ())
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
          : 
 var test = Optional<Int>(nilLiteral: ())
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      
      , Apple .