web-dev-qa-db-ja.com

Swiftの「ラップされていない値」とは何ですか?

私はiOS 8/OSX 10.10のSwiftを このチュートリアル と、「unwrapped value "は、この段落のように(Objects and Classの下で)数回使用されます。

オプションの値を使用する場合、次のように記述できますか?メソッド、プロパティ、添え字などの操作の前。 ?の前の値ゼロ、すべての後ですか?は無視され、式全体の値はnilです。それ以外の場合、オプションの値はラップ解除され、? アンラップ値に作用します。どちらの場合も、式全体の値はオプションの値です。

let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square") 
let sideLength = optionalSquare?.sideLength

私はそれを取得せず、運のないウェブ上で検索しました。

これはどういう意味ですか?


編集

Cezaryの回答から、元のコードの出力と最終的なソリューション(プレイグラウンドでテスト済み)にはわずかな違いがあります。

元のコード

Original code

セザリーのソリューション

Cezary's solution

2番目のケースではスーパークラスのプロパティが出力に表示されますが、最初のケースでは空のオブジェクトがあります。

どちらの場合でも結果は同一であるはずではありませんか?

関連するQ&A: Swiftのオプション値は何ですか?

154
Bigood

最初に、オプションタイプとは何かを理解する必要があります。オプションの型とは、基本的に、変数nilになり得ることを意味します。

例:

var canBeNil : Int? = 4
canBeNil = nil

疑問符は、canBeNilnilになる可能性があることを示しています。

これは機能しません:

var cantBeNil : Int = 4
cantBeNil = nil // can't do this

オプションの変数から値を取得するには、unwrap itにする必要があります。これは、感嘆符を最後に付けることを意味します。

var canBeNil : Int? = 4
println(canBeNil!)

コードは次のようになります。

let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square") 
let sideLength = optionalSquare!.sideLength

補足:

疑問符の代わりに感嘆符を使用して、自動的に展開するオプションを宣言することもできます。

例:

var canBeNil : Int! = 4
print(canBeNil) // no unwrapping needed

したがって、コードを修正する別の方法は次のとおりです。

let optionalSquare: Square! = Square(sideLength: 2.5, name: "optional square") 
let sideLength = optionalSquare.sideLength

編集:

表示される違いは、オプション値がwrappedであるという事実の症状です。その上に別のレイヤーがあります。 nwrappedバージョンは、まっすぐなオブジェクトを表示するだけです。

簡単な遊び場の比較:

playground

最初と2番目のケースでは、オブジェクトは自動的にアンラップされないため、2つの「レイヤー」({{...}})が表示されますが、3番目のケースでは、1つのレイヤー({...})オブジェクトは自動的にアンラップされます。

最初のケースと2番目の2つのケースの違いは、optionalSquarenilに設定されている場合、2番目の2つのケースでは実行時エラーが発生することです。最初のケースの構文を使用すると、次のようなことができます。

if let sideLength = optionalSquare?.sideLength {
    println("sideLength is not nil")
} else {
    println("sidelength is nil")
}
285
Cezary Wojcik

既存の正解は素晴らしいですが、これを完全に理解するには、非常に抽象的で奇妙な概念であるため、良い類推が必要であることがわかりました。

ですから、正解に加えて別の視点を与えることで、仲間の「右脳」(視覚的思考)開発者を助けさせてください。これは私を大いに助けた良い例えです。

誕生日プレゼントラッピングアナロジー

オプションは、硬くて硬い、色付きのラッピングが入った誕生日プレゼントのようなものだと考えてください。

現在の包装を解くまで、包装の中に何かが入っているかどうかはわかりません。中には何も入っていないかもしれません。内部に何かがある場合、それはさらに別の存在である可能性があり、これもラップされ、には何も含まれていない可能性があります。 100個のネストされたプレゼントのラップを解除して、最終的にラッピング以外のがないことを発見することもできます

オプションの値がnilでない場合、somethingを含むボックスが表示されます。ただし、特に値が明示的に入力されておらず、変数であり、事前定義された定数ではない場合、ボックスを開く必要がありますタイプなどのボックス、または実際のとは何ですか。

何が入っていますか?!類推

変数をアンラップした後でも、 SE7ENの最後のシーンwarning:ネタバレと非常にRに評価されたファウル言語では、ブラッドピットのようです。暴力)、プレゼントを開けた後でも、あなたは次の状況にいるからです:あなたは今nil、またはsomethingを含むボックスを持っている(しかし、あなたは何を知りません)

何かのタイプを知っているかもしれません。たとえば、変数を[Int:Any?]型であると宣言した場合、古い型のラップされたコンテンツを生成する整数の添え字を持つ(潜在的に空の)辞書があることがわかります。

そのため、Swiftでコレクション型(辞書と配列)を扱うのは、ちょっと面倒です。

適例:

typealias presentType = [Int:Any?]

func wrap(i:Int, gift:Any?) -> presentType? {
    if(i != 0) {
        let box : presentType = [i:wrap(i-1,gift:gift)]
        return box
    }
    else {
        let box = [i:gift]
        return box
    }
}

func getGift() -> String? {
    return "foobar"
}

let f00 = wrap(10,gift:getGift())

//Now we have to unwrap f00, unwrap its entry, then force cast it into the type we hope it is, and then repeat this in nested fashion until we get to the final value.

var b4r = (((((((((((f00![10]! as! [Int:Any?])[9]! as! [Int:Any?])[8]! as! [Int:Any?])[7]! as! [Int:Any?])[6]! as! [Int:Any?])[5]! as! [Int:Any?])[4]! as! [Int:Any?])[3]! as! [Int:Any?])[2]! as! [Int:Any?])[1]! as! [Int:Any?])[0])

//Now we have to DOUBLE UNWRAP the final value (because, remember, getGift returns an optional) AND force cast it to the type we hope it is

let asdf : String = b4r!! as! String

print(asdf)
16
CommaToast

Swiftは型の安全性を重視しています。 Swift言語全体は、安全性を考慮して設計されています。これはSwiftの特徴の1つであり、両手を広げて歓迎すべきものです。クリーンで読みやすいコードの開発を支援し、アプリケーションのクラッシュを防ぎます。

Swiftのすべてのオプションは、?シンボルで区切られます。オプションとして宣言している型の名前の後に?を設定すると、本質的にcastingになります。これは?の前の型としてではありません、代わりにoptionalタイプとして。


注:変数またはタイプIntは、notInt?と同じです。これらは互いに操作できない2つの異なるタイプです。


オプションを使用

var myString: String?

myString = "foobar"

これはnotを使用して、Stringのタイプで作業していることを意味します。これは、タイプString?(String Optional、またはOptional String)で作業していることを意味します。実際、あなたがしようとするたびに

print(myString)

実行時に、デバッグコンソールはOptional("foobar")を出力します。 「Optional()」の部分は、この変数が実行時に値を持つ場合と持たない場合があることを示していますが、実際には文字列「foobar」が含まれていることがあります。この「Optional()」の表示は、オプション値の「アンラップ」と呼ばれる処理を行わない限り残ります。

nwrappingオプションは、現在そのタイプを非オプションとしてキャストしていることを意味します。これにより、新しいタイプが生成され、そのオプション内に存在する値が新しい非オプションタイプに割り当てられます。この方法では、コンパイラーによって確実な値が保証されているため、その変数に対して操作を実行できます。


Conditionally Unwrappingは、オプションの値がnilであるかどうかを確認します。 nilでない場合、値とunwrappedが非オプションの定数に割り当てられる新しく作成された定数変数があります。そして、そこからifブロックで非オプションを安全に使用できます。

注:条件付きラップ解除定数には、ラップ解除するオプション変数と同じ名前を付けることができます。

if let myString = myString {
    print(myString)
    // will print "foobar"
}

条件付きアンラップオプションは、オプションの値にアクセスする最もクリーンな方法です。これには、nil値が含まれている場合、if letブロック内のすべてが実行されないためです。もちろん、ifステートメントのように、elseブロックを含めることができます

if let myString = myString {
    print(myString)
    // will print "foobar"
}
else {
    print("No value")
}

Forcibly Unwrappingは、!( "bang")演算子として知られているものを使用して行われます。これは安全性は劣りますが、それでもコードをコンパイルできます。ただし、bang演算子を使用するときは、強制的にアンラップする前に、変数に実際に固定値が含まれていることを1000%確実にする必要があります。

var myString: String?

myString = "foobar"

print(myString!)

これは完全に有効なSwiftコードです。 「foobar」として設定されたmyStringの値を出力します。ユーザーには、コンソールにfoobarと表示されますが、これで終わりです。しかし、値が設定されていないと仮定しましょう:

var myString: String?

print(myString!) 

今、私たちの手には異なる状況があります。 Objective-Cとは異なり、オプションを強制的にアンラップしようとし、オプションが設定されておらずnilである場合、オプションをアンラップしようとすると、アプリケーション内の内容がクラッシュします。


型キャストによるアンラッピング。前に言ったように、unwrappingオプションである場合、実際には非オプション型にキャストしますが、非オプション型を別のタイプにキャストすることもできます。例えば:

var something: Any?

コードのどこかで、変数somethingに値が設定されます。ジェネリックを使用している場合もあれば、これを変更する他のロジックが進行中の場合もあります。したがって、後のコードでは、somethingを使用しますが、異なる型の場合は別の方法で処理できます。この場合、asキーワードを使用してこれを決定します。

注:as演算子は、Swiftでキャストを入力する方法です。

// Conditionally
if let thing = something as? Int {
    print(thing) // 0
}

// Optionally
let thing = something as? Int
print(thing) // Optional(0)

// Forcibly
let thing = something as! Int
print(thing) // 0, if no exception is raised

2つのasキーワードの違いに注意してください。前と同様に、オプションを強制的にアンラップしたときは、! bang演算子を使用してアンラップしました。ここでも同じことを行いますが、オプションではないものとしてキャストする代わりに、Intとしてキャストします。そして、mustIntとしてダウンキャストできる必要があります。そうでなければ、値がnilのときにbang演算子を使用するなど、アプリケーションがクラッシュします。

そして、これらの変数をなんらかのソートまたは数学演算で使用するためには、それらをアンラップする必要があります。

たとえば、Swiftでは、同じ種類の有効な数値データ型のみが相互に操作できます。 as!で型をキャストすると、あたかもcertainであるかのように、その変数のダウンキャストが強制されます入力するので、安全に操作でき、アプリケーションをクラッシュさせることはありません。変数が実際にキャストする型である限り、これは問題ありません。そうでなければ、手に混乱が生じます。

それでも、as!を使用してキャストすると、コードをコンパイルできます。 as?でキャストすることは別の話です。実際、as?Intを完全に異なるデータ型として宣言します。

現在はOptional(0)です

そして、宿題をやろうとして

1 + Optional(1) = 2

あなたの数学の先生はおそらくあなたに「F」を与えたでしょう。 Swiftと同じです。 Swiftを除いて、成績を与えるのではなく、まったくコンパイルしません。 1日の終わりには、オプションは実際にはnilになる可能性があるため

安全第一キッズ。

13
Brandon A

「?」オプションの連鎖式を意味します

「!」の意味は力の値
enter image description here

0
gkgy