Appleのドキュメントから:
if
とをlet
一緒に使用して、欠落している可能性のある値を処理できます。これらの値はオプションとして表されます。オプションの値には、値が含まnil
れるか、値が欠落していることを示すためにが含まれます。?
値のタイプの後に疑問符()を記述して、値をオプションとしてマークします。
オプションの値を使用する理由は何ですか?
Appleのドキュメントから:
if
とをlet
一緒に使用して、欠落している可能性のある値を処理できます。これらの値はオプションとして表されます。オプションの値には、値が含まnil
れるか、値が欠落していることを示すためにが含まれます。?
値のタイプの後に疑問符()を記述して、値をオプションとしてマークします。
オプションの値を使用する理由は何ですか?
回答:
Swiftのオプションは、値を保持するか、値を保持しないタイプです。オプションは、?
任意のタイプにa を追加することによって記述されます。
var name: String? = "Bertie"
オプション(ジェネリックスと共に)は、理解するのが最も難しいSwiftの概念の1つです。それらがどのように記述および使用されているかにより、それらが何であるかについて誤った考えを得るのは簡単です。上記のオプションを通常の文字列の作成と比較します。
var name: String = "Bertie" // No "?" after String
構文から、オプションの文字列は通常の文字列に非常に似ているように見えます。そうではありません。オプションのストリングは、「オプション」設定がオンになっているストリングではありません。それは特別な種類の文字列ではありません。文字列とオプションの文字列は完全に異なるタイプです。
知っておくべき最も重要なことは次のとおりです。オプションは一種のコンテナーです。オプションの文字列は、文字列を含む可能性のあるコンテナです。オプションのIntは、Intを含むコンテナです。オプションを一種の小包と考えてください。それを開く(またはオプションの言語で「アンラップ」)する前に、何かが含まれているかどうかがわかりません。
Swift標準ライブラリでオプションがどのように実装されているかを確認するには、Swiftファイルに「オプション」と入力し、⌘クリックします。定義の重要な部分は次のとおりです。
enum Optional<Wrapped> {
case none
case some(Wrapped)
}
オプションは、またはenum
の2つのケースのいずれかになる可能性がある単なるです。の場合、関連する値があり、上記の例では「Hello」になります。オプションでGenericsを使用して、関連付けられた値にタイプを指定します。オプションの文字列のタイプではありません、それはだ、またはより正確に。.none
.some
.some
String
String
Optional
Optional<String>
Swiftがオプションで行うことはすべて、コードの読み書きをより流暢にする魔法です。残念ながら、これにより実際の動作がわかりにくくなります。後でいくつかのトリックを実行します。
注:オプションの変数についてよく説明しますが、オプションの定数を作成してもかまいません。作成される型の型を理解しやすくするために、すべての変数に型を付けていますが、独自のコードで記述する必要はありません。
オプションを作成するには、?
ラップするタイプの後にa を追加します。独自のカスタムタイプであっても、任意のタイプをオプションにすることができます。タイプとの間にスペースを入れることはできません?
。
var name: String? = "Bob" // Create an optional String that contains "Bob"
var peter: Person? = Person() // An optional "Person" (custom type)
// A class with a String and an optional String property
class Car {
var modelName: String // must exist
var internalName: String? // may or may not exist
}
オプションのto nil
を比較して、値があるかどうかを確認できます。
var name: String? = "Bob"
name = nil // Set name to nil, the absence of a value
if name != nil {
print("There is a name")
}
if name == nil { // Could also use an "else"
print("Name has no value")
}
これは少し混乱します。これは、オプションが何らかのものであることを意味します。それはnilか「ボブ」です。これは本当ではありません、オプションは他のものに変形しません。それをnilと比較することは、コードを読みやすくするためのトリックです。オプションがnilの場合、これは列挙型が現在に設定されていることを意味し.none
ます。
オプション以外の変数をnilに設定しようとすると、エラーが発生します。
var red: String = "Red"
red = nil // error: nil cannot be assigned to type 'String'
オプションを見る別の方法は、通常のSwift変数を補足するものです。これらは、値を持つことが保証されている変数に対応しています。Swiftはあいまいさを嫌う慎重な言語です。ほとんどの変数は非オプションとして定義されていますが、これが不可能な場合もあります。たとえば、キャッシュまたはネットワークから画像をロードするビューコントローラーを想像してみてください。ビューコントローラーの作成時に、その画像が含まれる場合と含まれない場合があります。image変数の値を保証する方法はありません。この場合、オプションにする必要があります。これはnil
、画像が取得されたときに始まり、オプションで値を取得します。
オプションを使用すると、プログラマの意図が明らかになります。オブジェクトがnilになる可能性のあるObjective-Cと比較すると、Swiftでは、値が欠落している可能性がある場合、および値が存在することが保証されている場合を明確にする必要があります。
オプションString
を実際のの代わりに使用することはできませんString
。オプション内でラップされた値を使用するには、ラップを解除する必要があります。オプションをアンラップする最も簡単な方法は!
、オプション名の後にを追加することです。これを「強制アンラップ」と呼びます。オプション内の値を(元のタイプとして)返しますが、オプションがの場合はnil
、ランタイムクラッシュが発生します。アンラップする前に、値があることを確認する必要があります。
var name: String? = "Bob"
let unwrappedName: String = name!
print("Unwrapped name: \(unwrappedName)")
name = nil
let nilName: String = name! // Runtime crash. Unexpected nil.
ラップを解除してオプションを使用する前に、常にnilをチェックする必要があるため、これは一般的なパターンです。
var mealPreference: String? = "Vegetarian"
if mealPreference != nil {
let unwrappedMealPreference: String = mealPreference!
print("Meal: \(unwrappedMealPreference)") // or do something useful
}
このパターンでは、値が存在することを確認し、存在することが確実な場合は、使用するために一時定数に強制的にアンラップします。これはよくあることなので、Swiftは「if let」を使用したショートカットを提供しています。これは「オプションのバインディング」と呼ばれます。
var mealPreference: String? = "Vegetarian"
if let unwrappedMealPreference: String = mealPreference {
print("Meal: \(unwrappedMealPreference)")
}
これは、(あなたが交換した場合や、変数の一時的な定数を作成しlet
てvar
)、その範囲の場合のみの括弧内にあります。「unwrappedMealPreference」や「realMealPreference」などの名前を使用する必要があるため、Swiftでは元の変数名を再利用して、ブラケットスコープ内に一時的な名前を作成できます。
var mealPreference: String? = "Vegetarian"
if let mealPreference: String = mealPreference {
print("Meal: \(mealPreference)") // separate from the other mealPreference
}
次に、別の変数が使用されていることを示すコードをいくつか示します。
var mealPreference: String? = "Vegetarian"
if var mealPreference: String = mealPreference {
print("Meal: \(mealPreference)") // mealPreference is a String, not a String?
mealPreference = "Beef" // No effect on original
}
// This is the original mealPreference
print("Meal: \(mealPreference)") // Prints "Meal: Optional("Vegetarian")"
オプションのバインディングは、オプションがnilに等しいかどうかを確認することによって機能します。含まれていない場合は、オプションを提供された定数にラップして、ブロックを実行します。Xcode 8.3以降(Swift 3.1)では、このようなオプションを印刷しようとすると、役に立たない警告が表示されます。オプションを使用しdebugDescription
て沈黙させます。
print("\(mealPreference.debugDescription)")
オプションには2つの使用例があります。
いくつかの具体的な例:
middleName
またはクラスspouse
内にある、またはないプロパティPerson
weak
クラスのプロパティ。彼らが指すものnil
はいつでも設定できますBoolean
オプションはObjective-Cには存在しませんが、nilを返す同等の概念があります。オブジェクトを返すことができるメソッドは、代わりにnilを返すことができます。これは「有効なオブジェクトが存在しない」という意味で使用され、何かがおかしいと言ってよく使われます。Objective-Cオブジェクトでのみ機能し、プリミティブや基本的なCタイプ(列挙型、構造体)では機能しません。Objective-Cのは、多くの場合、これらの値が存在しない表現するための型を特化した(NSNotFound
本当にNSIntegerMax
、kCLLocationCoordinate2DInvalid
座標無効表すために、-1
またはいくつかの負の値も使用されています)。コーダーはこれらの特別な値について知っている必要があるので、それらは各ケースについて文書化され、学習されなければなりません。メソッドがnil
パラメーターとして使用できない場合は、これを文書化する必要があります。Objective-Cでは、nil
すべてのオブジェクトがポインターとして定義されているのと同じようにポインターでしたがnil
、特定の(ゼロ)アドレスを指しています。Swiftでは、nil
は特定のタイプがないことを意味するリテラルです。
nil
以前は、任意のオプションをとして使用できましたBoolean
:
let leatherTrim: CarExtras? = nil
if leatherTrim {
price = price + 1000
}
Swiftの最近のバージョンでは、を使用する必要がありますleatherTrim != nil
。どうしてこれなの?問題はBoolean
、オプションでラップできることです。Boolean
このような場合:
var ambiguous: Boolean? = false
「false」には2種類あります。1つは値がない場合と、値はあるが値がの場合ですfalse
。Swiftはあいまいさを嫌うので、オプションをに対して常にチェックする必要がありnil
ます。
オプションのポイントBoolean
は何ですか?他のオプションと同様に、.none
状態は値がまだ不明であることを示す可能性があります。ネットワークコールの反対側に、ポーリングに時間がかかるものがある可能性があります。オプションのブール値も「とも呼ばれる3値ブール」
Swiftはオプションを機能させるためにいくつかのトリックを使用しています。次の3行の普通に見えるオプションのコードを考えてみてください。
var religiousAffiliation: String? = "Rastafarian"
religiousAffiliation = nil
if religiousAffiliation != nil { ... }
これらの行はコンパイルできません。
String
タイプだったとしてもこれらの行を機能させるオプションの実装の詳細をいくつか見ていきます。
使用する?
オプションを作成することはスウィフトコンパイラで有効になって、シンタックスシュガーです。長い道のりをしたい場合は、次のようなオプションを作成できます。
var name: Optional<String> = Optional("Bob")
これはOptional
、の最初の初期化子を呼び出します。これはpublic init(_ some: Wrapped)
、括弧内で使用されている型からオプションの関連型を推測します。
オプションを作成して設定するさらに長い方法:
var serialNumber:String? = Optional.none
serialNumber = Optional.some("1234")
print("\(serialNumber.debugDescription)")
nil
初期値なしのオプションを作成することも、初期値のオプションを作成することもできますnil
(どちらも同じ結果になります)。
var name: String?
var name: String? = nil
オプションに等しいことを許可することnil
は、プロトコルExpressibleByNilLiteral
(以前の名前はNilLiteralConvertible
)によって有効になります。オプションはOptional
の2番目のイニシャライザで作成されますpublic init(nilLiteral: ())
。ドキュメントExpressibleByNilLiteral
では、コード内のnilの意味が変わるため、オプション以外は使用しないでくださいと言っていますが、可能です。
class Clint: ExpressibleByNilLiteral {
var name: String?
required init(nilLiteral: ()) {
name = "The Man with No Name"
}
}
let clint: Clint = nil // Would normally give an error
print("\(clint.name)")
同じプロトコルを使用すると、作成済みのオプションをに設定できますnil
。推奨されませんが、nilリテラル初期化子を直接使用できます。
var name: Optional<String> = Optional(nilLiteral: ())
nil
オプションは、2つの特別な「==」および「!=」演算子をOptional
定義します。これらは定義で確認できます。1つ目==
は、オプションがnilと等しいかどうかをチェックすることを可能にします。.noneに設定された2つの異なるオプションは、関連付けられたタイプが同じである場合、常に等しくなります。nilと比較すると、バックグラウンドでSwiftが同じ関連タイプのオプションを作成し、.noneに設定してから比較に使用します。
// How Swift actually compares to nil
var tuxedoRequired: String? = nil
let temp: Optional<String> = Optional.none
if tuxedoRequired == temp { // equivalent to if tuxedoRequired == nil
print("tuxedoRequired is nil")
}
2番目の==
演算子を使用すると、2つのオプションを比較できます。どちらも同じタイプである必要があり、そのタイプは準拠する必要がEquatable
あります(通常の「==演算子で物事を比較できるプロトコル」)。Swiftは(おそらく)2つの値をアンラップし、それらを直接比較します。また、オプションの一方または両方がである場合も処理します.none
。nil
リテラルと比較する際の違いに注意してください。
さらに、任意のEquatable
型をその型のオプションのラッピングと比較できます。
let numberToFind: Int = 23
let numberFromString: Int? = Int("23") // Optional(23)
if numberToFind == numberFromString {
print("It's a match!") // Prints "It's a match!"
}
Swiftは比較の前に、非オプションをオプションとしてラップします。リテラルでも動作します(if 23 == numberFromString {
)
==
演算子は2つあると言いましたが、実際nil
には比較の左側に配置できる3 つ目の演算子があります
if nil == name { ... }
オプションタイプに非オプションタイプとは異なる名前を付けるためのSwiftの規則はありません。人々はそれがオプションであることを示すために名前に何かを追加することを避け( "optionalMiddleName"や "possibleNumberAsString"など)、宣言にそれがオプションのタイプであることを示します。オプションからの値を保持するために何かに名前を付けたい場合、これは難しくなります。「middleName」という名前は、それがString型であることを意味するため、そこからString値を抽出すると、「actualMiddleName」、「unwrappedMiddleName」、「realMiddleName」などの名前になることがよくあります。これを回避するには、オプションのバインディングを使用し、変数名を再利用します。
Swiftプログラミング言語の「The Basics」から:
Swiftには、値の欠落を処理するオプションのタイプも導入されています。オプションは、「値があり、xに等しい」または「値がまったくない」と言います。オプションは、Objective-Cでnilをポインターと共に使用するのと似ていますが、クラスだけでなく、どのタイプでも機能します。オプションは、Objective-Cのnilポインターよりも安全で表現力があり、Swiftの最も強力な機能の多くの中心にあります。
オプションは、Swiftがタイプセーフ言語であるという事実の例です。Swiftは、コードで処理できる値のタイプを明確にするのに役立ちます。コードの一部に文字列が必要な場合、タイプセーフにより、誤ってそれをIntに渡すことが防止されます。これにより、開発プロセスのできるだけ早い段階でエラーをキャッチして修正できます。
最後に、1899年のオプションについての詩を次に示します。
昨日階段時に
、私はバーバーが満たさ
彼が今日もなかった
私が望む、私は彼が離れて行くと思いたい
アンティゴニッシュを
の例を見てみましょう。NSError
エラーが返されない場合は、Nilを返すことをオプションにしたいとします。エラーがなければ、値を割り当てても意味がありません。
var error: NSError? = nil
これにより、デフォルト値を設定することもできます。したがって、関数に何も渡されない場合は、メソッドをデフォルト値に設定できます
func doesntEnterNumber(x: Int? = 5) -> Bool {
if (x == 5){
return true
} else {
return false
}
}
func isNil<T>(t: T?) -> Bool { return t == nil }
返されます。true
nil
return x == 5
か?5の何がそんなに特別なのですか?
私は上記のほとんどを要約した短い答えを出し、初心者として私の頭にあった不確実性を取り除きました:
Objective-Cとは異なり、Swiftでは変数にnilを含めることはできないため、オプションの変数タイプが追加されました(変数の接尾辞は「?」)。
var aString = nil //error
大きな違いは、オプションの変数は(通常のObj-C変数のように)値を直接格納しないことです。これらの変数には2つの状態が含まれます。「値がある」または「nilがある」:
var aString: String? = "Hello, World!"
aString = nil //correct, now it contains the state "has nil"
つまり、さまざまな状況でこれらの変数を確認できます。
if let myString = aString? {
println(myString)
}
else {
println("It's nil") // this will print in our case
}
「!」を使用する サフィックス、それらが存在する場合にのみ、それらにラップされた値にアクセスすることもできます。(つまり、それはnilではありません):
let aString: String? = "Hello, World!"
// var anotherString: String = aString //error
var anotherString: String = aString!
println(anotherString) //it will print "Hello, World!"
そのため、「?」を使用する必要があります。そして「!」デフォルトではすべてを使用するわけではありません。(これは私の最大の困惑でした)
上記の答えにも同意します。オプションの型はブール値として使用できません。
値のない目的Cの変数は「nil」に等しいため(0やfalseと同じ「nil」の値を使用することも可能)、条件付きステートメントで変数を使用することが可能でした(値を持つ変数は「TRUE」と同じです) 'と値のないものは' FALSE 'に等しい)。
Swiftは「オプションの値」を提供することでタイプセーフを提供します。つまり、異なるタイプの変数を割り当てることによって形成されるエラーを防ぎます。
したがって、Swiftでは、条件付きステートメントで提供できるのはブール値のみです。
var hw = "Hello World"
ここでは、「hw」は文字列ですが、目的Cのようなifステートメントでは使用できません。
//This is an error
if hw
{..}
そのため、次のように作成する必要があります。
var nhw : String? = "Hello World"
//This is correct
if nhw
{..}
オプションの値を使用すると、値がないことを示すことができます。SQLのNULLやObjective-CのNSNullに少し似ています。これは「プリミティブ」タイプでも使用できるので、改善になると思います。
// Reimplement the Swift standard library's optional type
enum OptionalValue<T> {
case None
case Some(T)
}
var possibleInteger: OptionalValue<Int> = .None
possibleInteger = .Some(100)”
抜粋:Apple Inc.「The Swift Programming Language」iBooks。https://itun.es/gb/jEUH0.l
nil
enum定数のためだけの構文糖であるOptionalValue<T>.None
(T
あなたが使用しているコンテキストにタイプが適切であるがnil
)。?
のショートカットですOptionalValue<T>.Some(T)
。
オプションは、値がタイプに対応するかどうかをSwiftが完全に確信できないことを意味します。たとえば、Int?つまり、Swiftは、数値がIntであるかどうかを完全には確信していません。
それを削除するには、3つの方法があります。
1)タイプが確実にわかっている場合は、次のように感嘆符を使用して強制的にアンラップできます。
// Here is an optional variable:
var age: Int?
// Here is how you would force unwrap it:
var unwrappedAge = age!
オプションを強制的にアンラップし、それがnilに等しい場合、このクラッシュエラーが発生する可能性があります。
これは必ずしも安全であるとは限らないため、タイプと値がわからない場合にクラッシュを防ぐ方法を次に示します。
方法2と3は、この問題に対する保護手段です。
2)暗黙的にアンラップされたオプション
if let unwrappedAge = age {
// continue in here
}
ラップされていない型がIntではなくIntになっていることに注意してください。。
3)ガードステートメント
guard let unwrappedAge = age else {
// continue in here
}
ここから先に進んで、ラップされていない変数を使用できます。変数の型が確実である場合は、(!を使用して)アンラップを強制するようにしてください。
あなたのプロジェクトで頑張ってください!
私が学び始めたときSwift
、なぜオプションであるかを理解することは非常に困難でした。
このように考えましょう。クラスについて考えてみましょうPerson
2つの性質を持っているname
としますcompany
。
class Person: NSObject {
var name : String //Person must have a value so its no marked as optional
var companyName : String? ///Company is optional as a person can be unemployed that is nil value is possible
init(name:String,company:String?) {
self.name = name
self.companyName = company
}
}
いくつかのオブジェクトを作成しましょう Person
var tom:Person = Person.init(name: "Tom", company: "Apple")//posible
var bob:Person = Person.init(name: "Bob", company:nil) // also Possible because company is marked as optional so we can give Nil
しかし、我々は渡すことはできませんNil
にname
var personWithNoName:Person = Person.init(name: nil, company: nil)
では、なぜ私たちが使用するのかについて話しましょうoptional?
。willのInc
ように会社名の後に追加したい状況を考えてみapple
ましょうapple Inc
。Inc
会社名の後に追加して印刷する必要があります。
print(tom.companyName+" Inc") ///Error saying optional is not unwrapped.
print(tom.companyName!+" Inc") ///Error Gone..we have forcefully unwrap it which is wrong approach..Will look in Next line
print(bob.companyName!+" Inc") ///Crash!!!because bob has no company and nil can be unwrapped.
次に、オプションが行われる理由を調べてみましょう。
if let companyString:String = bob.companyName{///Compiler safely unwrap company if not nil.If nil,no unwrap.
print(companyString+" Inc") //Will never executed and no crash!!!
}
置き換えることができますbob
でtom
if let companyString:String = tom.companyName{///Compiler safely unwrap company if not nil.If nil,no unwrap.
print(companyString+" Inc") //Will never executed and no crash!!!
}
そしておめでとうございます!私たちは適切に対処しましたoptional?
したがって、実現ポイントは
nil
nil
いる場合、その変数を適切に処理しているかどうかを確認する必要があることを通知します。ありがとう...ハッピーコーディング
以下のコードPlaygroundを試してみ ましょう。オプションが何であり、それを使用する理由が明確になることを願っています。
var sampleString: String? ///Optional, Possible to be nil
sampleString = nil ////perfactly valid as its optional
sampleString = "some value" //Will hold the value
if let value = sampleString{ /// the sampleString is placed into value with auto force upwraped.
print(value+value) ////Sample String merged into Two
}
sampleString = nil // value is nil and the
if let value = sampleString{
print(value + value) ///Will Not execute and safe for nil checking
}
// print(sampleString! + sampleString!) //this line Will crash as + operator can not add nil
オプションの連鎖は、現在はnilである可能性があるオプションのプロパティ、メソッド、および添え字を照会および呼び出すプロセスです。オプションに値が含まれている場合、プロパティ、メソッド、または添え字の呼び出しは成功します。オプションがnilの場合、プロパティ、メソッド、または添え字の呼び出しはnilを返します。複数のクエリをチェーンすることができ、チェーン内のリンクがnilの場合、チェーン全体が正常に失敗します。
より深く理解するには、上のリンクを読んでください。
上手...
?(オプション)変数にnil値が含まれている可能性があることを示します。(unwrapper)は、実行時に変数を使用する(値を取得しようとする)ときに、変数にメモリ(または値)が必要であることを示します。
主な違いは、オプションがnilの場合、オプションのチェーニングは正常に失敗するのに対し、オプションがnilの場合、強制アンラップはランタイムエラーをトリガーします。
オプションのチェーンをnil値で呼び出すことができるという事実を反映するために、オプションのチェーン呼び出しの結果は、クエリしているプロパティ、メソッド、または添え字がオプションではない値を返した場合でも、常にオプションの値になります。このオプションの戻り値を使用して、オプションのチェーン呼び出しが成功した(返されたオプションに値が含まれている)か、チェーン内のnil値が原因で失敗した(返されたオプション値はnil)かを確認できます。
具体的には、オプションのチェーン呼び出しの結果は、予期される戻り値と同じ型ですが、オプションでラップされます。通常Intを返すプロパティは、ますか?オプションの連鎖を通じてアクセスした場合。
var defaultNil : Int? // declared variable with default nil value
println(defaultNil) >> nil
var canBeNil : Int? = 4
println(canBeNil) >> optional(4)
canBeNil = nil
println(canBeNil) >> nil
println(canBeNil!) >> // Here nil optional variable is being unwrapped using ! mark (symbol), that will show runtime error. Because a nil optional is being tried to get value using unwrapper
var canNotBeNil : Int! = 4
print(canNotBeNil) >> 4
var cantBeNil : Int = 4
cantBeNil = nil // can't do this as it's not optional and show a compile time error
ここでAppleデベロッパ委員会による詳細な基本的なチュートリアルでは、次のとおりです。オプションの連鎖
Swiftのオプションは、値を保持するか、値を保持しないタイプです。オプションは、?任意のタイプに:
var name: String?
このリンクを参照して、深い知識を得ることができます:https : //medium.com/@agoiabeladeyemi/optionals-in-swift-2b141f12f870
Swiftでの同等のオプション宣言は次のとおりです。
var middleName: String?
この宣言は、String型のmiddleNameという名前の変数を作成します。String変数タイプの後の疑問符(?)は、middleName変数に、Stringまたはnilのいずれかの値を含めることができることを示しています。このコードを見ると、middleNameがnilになる可能性があることがすぐにわかります。それは自己文書化です!
(上記のように)オプションの定数または変数の初期値を指定しない場合、値は自動的にnilに設定されます。必要に応じて、初期値を明示的にnilに設定できます。
var middleName: String? = nil
リンクの下のオプションの詳細については
http://www.iphonelife.com/blog/31369/swift-101-working-swifts-new-optional-values