534

Swift プログラミング言語ガイドには、次の例があります。

class Person {
    let name: String
    init(name: String) { self.name = name }
    var apartment: Apartment?
    deinit { println("\(name) is being deinitialized") }
}

class Apartment {
    let number: Int
    init(number: Int) { self.number = number }
    var tenant: Person?
    deinit { println("Apartment #\(number) is being deinitialized") }
}

var john: Person?
var number73: Apartment?

john = Person(name: "John Appleseed")
number73 = Apartment(number: 73)

//From Apple's “The Swift Programming Language” guide (https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html)

次に、アパートを人に割り当てるときに、感嘆符を使用して「インスタンスをアンラップ」します。

john!.apartment = number73

「インスタンスをアンラップする」とはどういう意味ですか? なぜそれが必要なのですか?次のことを行うのとどう違うのですか?

john.apartment = number73

私はSwift言語に非常に慣れていません。基本を押さえようとしているだけです。


更新:
私が見逃していたパズルの大きなピース(回答には直接記載されていません-少なくともこれを書いている時点ではありません)は、次のことを行うときです:

var john: Person?

john私が最初に考えたように、それは「型Personであり、nilかもしれない」という意味ではありません。PersonPerson?は完全に別のタイプだと単純に誤解していました。それを理解すると、他のすべて?!狂気、および以下の素晴らしい答えがより理にかなっています.

4

23 に答える 23

547

「インスタンスをアンラップする」とはどういう意味ですか? なぜそれが必要なのですか?

私が解決できる限り(これは私にとっても非常に新しいことです)...

「ラップされた」という用語は、Optional 変数を (悲しいことに!) 空である可能性がある光沢のある紙に包まれたプレゼントと考える必要があることを意味します。

「ラップ」すると、Optional 変数の値は 2 つの可能な値を持つ列挙型になります (ブール値に少し似ています)。この列挙型は、変数が値を保持するか ( Some(T))、保持しないか ( None) を示します。

値がある場合は、変数を「アンラップ」することで取得できます ( Tfromを取得しますSome(T))。

とどうjohn!.apartment = number73違うのjohn.apartment = number73?(言い換え)

Optional 変数の名前を記述する場合 (例: text john!なし)、これは値自体 (T) ではなく、「ラップされた」列挙型 (Some/None) を参照します。Sojohnは のインスタンスでPersonはなく、メンバーもありませんapartment:

john.apartment
// 'Person?' does not have a member named 'apartment'

実際のPerson値は、さまざまな方法でアンラップできます。

  • "forced unwrapping": john!(Person存在する場合は値を返し、nil の場合は実行時エラーを返します)
  • "optional binding": if let p = john { println(p) }(println値が存在する場合に実行します)
  • "optional chaining": john?.learnAboutSwift()(値が存在する場合、この作成されたメソッドを実行します)

nil の場合に何が起こるか、およびその可能性に応じて、ラップを解除するこれらの方法のいずれかを選択すると思います。この言語設計では、nil ケースを明示的に処理する必要があります。これにより、Obj-C (nil ケースの処理を忘れがち) よりも安全性が向上すると思います。

更新

感嘆符は、"Implicitly Unwrapped Optionals" を宣言するための構文でも使用されます。

これまでの例では、john変数は として宣言されておりvar john:Person?、オプションです。その変数の実際の値が必要な場合は、上記の 3 つの方法のいずれかを使用してラップを解除する必要があります。

代わりに宣言された場合var john:Person!、変数は Implicitly Unwrapped Optional になります (Apple の本のこの見出しのセクションを参照してください)。値にアクセスするときにこの種の変数をラップ解除する必要はなく、john追加の構文なしで使用できます。しかし、Apple の本には次のように書かれています。

変数が後で nil になる可能性がある場合は、暗黙的にラップ解除されたオプションを使用しないでください。変数の存続期間中に nil 値をチェックする必要がある場合は、常に通常のオプションの型を使用してください。

更新 2 :

Mike Ash による記事「Interesting Swift Features 」は、オプションの型についていくつかの動機を与えてくれます。分かりやすく素晴らしい文章だと思います。

更新 3 :

感嘆符の暗黙のアンラップされたオプションの使用に関する別の有用な記事: Chris Adamson による「 Swift and the Last Mile 」。この記事では、これはAppleがnilを含む可能性のあるObjective-Cフレームワークで使用される型を宣言するために使用する実用的な手段であると説明しています. 型をオプション ( を使用?) または暗黙的にアンラップ ( を使用) として宣言すること!は、「安全性と利便性のトレードオフ」です。この記事に記載されている例では、Apple は型を暗黙的にラップ解除されていると宣言することを選択したため、呼び出しコードはより便利になりますが、安全性は低下します。

おそらく、Apple は将来的にフレームワークを精査し、暗黙的にアンラップされた (「おそらく決して nil ではない」) パラメータの不確実性を取り除き、それらをオプション (「特に [願わくば、文書化された!] 状況では確かに nil になる可能性がある」) または標準的な非-Objective-C コードの正確な動作に基づいたオプション (「決して nil ではない」) 宣言。

于 2014-06-03T17:04:07.737 に答える
129

私が思う違いは以下です。

var john: Person?

johnがnilになる可能性があることを意味します

john?.apartment = number73

コンパイラは、この行を次のように解釈します。

if john != nil {
    john.apartment = number73
}

その間

john!.apartment = number73

コンパイラは、この行を単純に次のように解釈します。

john.apartment = number73

したがって、を使用!すると if ステートメントがラップ解除され、実行が高速になりますが、john が nil の場合、実行時エラーが発生します。

したがって、ここでのラップは、メモリがラップされていることを意味するのではなく、コードがラップされていることを意味します。この場合は if ステートメントでラップされています。Apple は実行時のパフォーマンスに細心の注意を払っているため、アプリを可能な限り最高のパフォーマンスで実行します。

アップデート:

Stackoverflowで最高の評判を得たので、4年後にこの回答に戻ってきました:)当時、アンラップの意味を少し誤解していました。4年経った今、ここでアンラップすることの意味は、元のコンパクトな形式からコードを拡張することだと信じています. また、定義上、nil であるかどうかわからないため、そのオブジェクトの周囲のあいまいさを取り除くことも意味します。上記のアシュリーの答えのように、何も入っていないプレゼントと考えてください。しかし、アンラップはコードアンラップであり、列挙型を使用するメモリベースのアンラップではないと思います。

于 2014-06-20T04:16:44.460 に答える
69

TL;DR

Swift言語で感嘆符は何を意味しますか?

感嘆符は効果的に次のように述べています。使ってください。」これは、オプションの値の強制アンラップとして知られています。

let possibleString: String? = "An optional string."
print(possibleString!) // requires an exclamation mark to access its value
// prints "An optional string."

let assumedString: String! = "An implicitly unwrapped optional string."
print(assumedString)  // no exclamation mark is needed to access its value
// prints "An implicitly unwrapped optional string."

ソース: https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-XID_399

于 2014-07-17T02:22:28.013 に答える
37

john がオプションの var である場合 (このように宣言されます)

var john: Person?

その場合、john が値を持たない可能性があります (ObjC の用語では nil 値)。

感嘆符は基本的にコンパイラに「これには値があることを知っています。テストする必要はありません」と伝えます。使用したくない場合は、条件付きでテストできます。

if let otherPerson = john {
    otherPerson.apartment = number73
}

this の内部は、john に値がある場合にのみ評価されます。

于 2014-06-03T15:00:36.883 に答える
24
于 2014-06-03T14:54:39.510 に答える
16

ここではいくつかの例を示します。

var name:String = "Hello World"
var word:String?

はオプションwordの値です。値を含む場合と含まない場合があることを意味します。

word = name 

ここnameに値があるので、それを割り当てることができます

var cow:String = nil
var dog:String!

強制的にアンラップされる場所dogは、値が含まれている必要があることを意味します

dog = cow

nilunwrappedに割り当てられているため、アプリケーションがクラッシュします

于 2015-07-10T08:32:27.630 に答える
14

この場合...

var John: 人!

つまり、John の最初の値は nil であり、設定され、一度設定されると、再び nil になることはありません。したがって、便宜上、オプションの変数にアクセスするためのより簡単な構文を使用できます。これは「暗黙的にラップ解除されたオプション」であるためです。

于 2014-07-24T21:50:01.867 に答える
3

C# に精通している場合、これは疑問符を使用して宣言される Nullable 型のようなものです。

Person? thisPerson;

この場合の感嘆符は、次のように null 許容型の .Value プロパティにアクセスすることと同じです。

thisPerson.Value
于 2015-10-20T14:23:42.267 に答える
3

!オブジェクトを強制的にアンラップしていることを意味します ! 続きます。詳細については、https ://developer.apple.com/library/ios/documentation/swift/conceptual/Swift_Programming_Language/TheBasics.html にある Apple のドキュメントを参照してください。

于 2014-11-16T02:30:05.567 に答える
2

目的の C 変数では、値のない変数は「nil」に等しくなり (0 および false と同じ「nil」値を使用することも可能でした)、したがって、条件文で変数を使用することができました (値を持つ変数は「TRUE」と同じです) ' であり、値のないものは 'FALSE' に等しかった)。

Swift は、「オプションの値」を提供することで型の安全性を提供します。つまり、異なるタイプの変数を割り当てることによって形成されるエラーを防ぎます。

そのため、Swift では、条件ステートメントでブール値のみを指定できます。

var hw = "Hello World"

ここで、「hw」は文字列ですが、Objective C のように if ステートメントでは使用できません。

//This is an error

if hw

 {..}

そのためには、次のように作成する必要があります。

var nhw : String? = "Hello World"

//This is correct

if nhw

 {..}
于 2014-06-19T06:59:29.720 に答える
2

!オブジェクトの最後に、オブジェクトがオプションであり、それ以外の場合は nil を返すことができる場合はアンラップすることを示します。これは、そうでなければプログラムをクラッシュさせるエラーをトラップするためによく使用されます。

于 2015-06-09T06:09:20.947 に答える
2

要するに (!): 変数を宣言し、変数が値を保持していることを確認した後。

let assumedString: String! = "Some message..."
let implicitString: String = assumedString

それ以外の場合は、値を渡すたびにこれを行う必要があります...

let possibleString: String? = "An optional string."
let forcedString: String = possibleString! // requires an exclamation mark
于 2016-01-07T07:53:49.473 に答える
1

簡単に言うと、エクスクラメーション マークはオプションがアンラップされていることを意味します。オプションは、値を持つことも持たないこともできる変数です。したがって、ここに示すように if let ステートメントを使用して、変数が空かどうかを確認し、強制的にアンラップできます。ただし、空のオプションを強制的にアンラップすると、プログラムがクラッシュするので注意してください! オプションは、変数への明示的な割り当ての最後に疑問符を付けることで宣言されます。たとえば、次のように記述できます。

var optionalExample: String?

この変数には値がありません。それをアンラップすると、プログラムがクラッシュし、Xcode は、nil の値でオプションをアンラップしようとしたことを通知します。

それが役に立ったことを願っています。

于 2015-02-26T18:25:25.597 に答える
1

簡単な言葉で

USING 感嘆符は、変数が nil 以外の値で構成されている必要があることを示します (nil になることはありません)。

于 2016-05-23T13:03:00.597 に答える
1

John はオプションの Person であり、値を保持することも nil にすることもできます。

john.apartment = number73

john がオプションでない場合に使用されます。john は決して nil ではないので、nil 値で apartment を呼び出さないことは確実です。その間

john!.apartment = number73

は、john が nil ではないことをコンパイラに約束し、optional をアンラップして john の値を取得し、john のアパートメント プロパティにアクセスします。john が nil でないことがわかっている場合は、これを使用します。これを nil オプションで呼び出すと、実行時エラーが発生します。

ドキュメントには、convertedNumber がオプションである、これを使用するための良い例が含まれています。

if convertedNumber {
    println("\(possibleNumber) has an integer value of \(convertedNumber!)")
} else {
    println("\(possibleNumber) could not be converted to an integer")
}
于 2014-06-03T14:56:43.653 に答える
0
Simple the Optional variable allows nil to be stored.

var str : String? = nil

str = "Data"

To convert Optional to the Specific DataType, We unwrap the variable using the keyword "!"

func get(message : String){
   return
}

get(message : str!)  // Unwapped to pass as String
于 2016-10-25T04:58:57.903 に答える
-1

自問してみてください

  • person?apartmentメンバー/プロパティがありますか? また
  • personapartmentメンバー/プロパティがありますか?

この質問に答えられない場合は、読み続けてください。

理解するには、 Genericsの超基本レベルの理解が必要になる場合があります。ここを参照してください。Swift の多くは Generics を使用して記述されています。オプション付属

以下のコードは、このスタンフォード ビデオから入手できます。最初の5分だけ見ることを強くお勧めします

Optional は、2 つのケースのみを持つ列挙型です

enum Optional<T>{
    case None
    case Some(T)
}

let x: String? = nil //actually means:

let x = Optional<String>.None

let x :String? = "hello" //actually means:

let x = Optional<String>.Some("hello")

var y = x! // actually means:

switch x {
case .Some(let value): y = value
case .None: // Raise an exception
}

オプションのバインディング:

let x:String? = something
if let y = x {
    // do something with y
}
//Actually means:

switch x{
case .Some(let y): print)(y) // or whatever else you like using 
case .None: break
}

あなたが言うとき、あなたはvar john: Person?実際にそのようなことを意味します:

enum Optional<Person>{
case .None
case .Some(Person)
}

上記の列挙型には、という名前のプロパティapartmentがありますか? どこかで見えますか?それはまったくありません!ただし、ラップを解除すると、つまり実行person!できます...フードの下で行うことは次のとおりです。Optional<Person>.Some(Person(name: "John Appleseed"))


var john: Person代わりに :を定義していたら、それ自体がのメンバーを持っているため、使用済みを使用var john: Person?する必要はなくなりました。!Personapartment


!アンラップを使用することが推奨されない理由に関する将来の議論として、この Q&Aを参照してください。

于 2016-08-08T13:30:17.273 に答える