「致命的なエラー:オプションの値のアンラップ中に予期せずnilが見つかりました」とはどういう意味ですか?

429
pkamb 2015-08-24 09:10.

私のSwiftプログラムはEXC_BAD_INSTRUCTION、次のいずれかの同様のエラーでクラッシュします。このエラーはどういう意味ですか、どうすれば修正できますか?

致命的なエラー:オプション値のアンラップ中に予期せずnilが見つかりました

または

致命的なエラー:オプションの値を暗黙的にアンラップしているときに、予期せずnilが見つかりました


この投稿は、「予期せず見つかったnil」の問題に対する回答を収集することを目的としているため、それらが散在して見つけにくいものではありません。独自の回答を追加するか、既存のWiki回答を編集してください。

11 answers

685
Hamish 2015-08-24 09:10.

この答えは「コミュニティWiki」の投稿とは何ですか?です。改善できると思われる場合は、お気軽に編集してください。

背景:オプションとは何ですか?

Swiftでは、Optional<Wrapped>オプションタイプです。元の(「ラップされた」)タイプの任意の値を含めることも、まったく値を含めない(特別な値nil)こともできます。オプションの値は、使用する前にラップを解除する必要があります。

オプションはジェネリック型です。これは、Optional<Int>Optional<String>が別個のであることを意味し<>ます。内部の型はラップ型と呼ばれます。内部的には、Optionalは2つのケースを持つ列挙型です:.some(Wrapped).none、ここで、はと.none同等nilです。

オプションは、名前付きタイプを使用して宣言するOptional<T>か、(最も一般的には)?接尾辞付きの省略形として宣言できます。

var anInt: Int = 42
var anOptionalInt: Int? = 42
var anotherOptionalInt: Int?  // `nil` is the default when no value is provided
var aVerboseOptionalInt: Optional<Int>  // equivalent to `Int?`

anOptionalInt = nil // now this variable contains nil instead of an integer

オプションは、コードを記述しながら仮定を表現するためのシンプルでありながら強力なツールです。コンパイラーはこの情報を使用して、ユーザーが間違いを犯さないようにすることができます。スウィフトプログラミング言語

Swiftはタイプセーフな言語です。つまり、この言語は、コードで使用できる値のタイプを明確にするのに役立ちます。コードの一部にが必要なString場合、型安全性によりInt、誤ってコードを渡すことを防ぎます。同様に、型安全性は、オプションStringを必要とするコードにオプションを誤って渡すことを防ぎますString型安全性は、開発プロセスのできるだけ早い段階でエラーを見つけて修正するのに役立ちます。

いくつかの他のプログラミング言語も、ジェネリック持っているオプションの種類を:例えば、たぶんHaskellの、でオプション錆であり、オプションのC ++ 17インチ

オプションタイプのないプログラミング言語では、有効な値がないことを示すために特定の「センチネル」値がよく使用されます。たとえば、Objective-Cでは、nilnullポインタ)はオブジェクトがないことを表します。以下のようなプリミティブ型の場合はint、あなたが別の変数(のようないずれかの必要がありますので、ヌルポインタが、使用できないvalue: IntisValid: Bool)、または指定されたセンチネル値を(など-1INT_MIN)。これらのアプローチはisValid、番兵の値を確認したり確認したりするのを忘れがちなため、エラーが発生しやすくなります。また、特定の値が番兵として選択された場合、それは有効な値として扱われなくなることを意味します。

SwiftなどのオプションタイプはOptional、特別な個別のnil値を導入し(したがって、番兵の値を指定する必要がない)、強力な型システムを活用することでこれらの問題を解決します。これにより、コンパイラーは、必要に応じてnilを忘れずにチェックできます。


致命的なエラー:オプションの値をアンラップしているときに予期せずnilが見つかりました」というメッセージが表示されたのはなぜですか?

オプションの値にアクセスするには(オプションがある場合)、それをアンラップする必要があります。オプションの値は、安全または強制的にアンラップできます。オプションを強制的にアンラップし、値がなかった場合、プログラムは上記のメッセージでクラッシュします。

Xcodeは、コード行を強調表示することでクラッシュを表示します。この行で問題が発生します。

このクラッシュは、2種類の強制アンラップで発生する可能性があります。

1.明示的な強制アンラッピング

これは!、オプションのオペレーターで行われます。例えば:

let anOptionalString: String?
print(anOptionalString!) // <- CRASH

致命的なエラー:オプション値のアンラップ中に予期せずnilが見つかりました

以下のようanOptionalStringであるnilここで、あなたはそれアンラップ強制ライン上でクラッシュを取得します。

2.暗黙的にアンラップされたオプション

これらは、タイプの後では!なく、で定義され?ます。

var optionalDouble: Double!   // this value is implicitly unwrapped wherever it's used

これらのオプションには値が含まれていると見なされます。したがって、暗黙的にアンラップされたオプションにアクセスすると、自動的に強制的にアンラップされます。値が含まれていない場合、クラッシュします。

print(optionalDouble) // <- CRASH

致命的なエラー:オプションの値を暗黙的にアンラップしているときに、予期せずnilが見つかりました

クラッシュの原因となった変数を特定するために、押したままクリックして定義を表示すると、オプションのタイプが見つかります。

特に、IBOutletsは通常、暗黙的にラップ解除されたオプションです。これは、初期化、実行時にxibまたはストーリーボードがアウトレットをリンクするためです。したがって、ロードする前にアウトレットにアクセスしていないことを確認する必要があります。また、ストーリーボード/ xibファイルで接続が正しいことを確認する必要があります。そうしないと、値がnil実行時になり、暗黙的にアンラップされるとクラッシュします。 。接続を修正するときは、コンセントを定義するコード行を削除してから、再接続してみてください。


オプションのアンラップを強制する必要があるのはいつですか?

明示的な強制アンラッピング

原則として、!演算子を使用してオプションを明示的に強制的にアンラップしないでください。使用!が許容される場合もありますが、オプションに値が含まれていることが100%確実である場合にのみ使用する必要があります。

そこにいる間、あなたが知っているように、あなたはアンラップ力を使用することができる機会があり、実際のオプションに値が含まれていること-がない、単一のオプションの代わりに、あなたが安全にアンラップすることができない場所。

暗黙的にアンラップされたオプション

これらの変数は、コードの後半まで割り当てを延期できるように設計されています。アクセスする前に、それらに価値があることを確認するのはあなたの責任です。ただし、強制的なアンラップが含まれるため、nilの割り当ては有効ですが、値がnil以外であると想定しているため、本質的に安全ではありません。

最後の手段として、暗黙的にラップされていないオプションのみを使用する必要があります。遅延変数を使用できる場合、または変数デフォルト値指定できる場合は、暗黙的にアンラップされたオプションを使用する代わりに、そうする必要があります。

ただし、暗黙的にアンラップされたオプションが有益であるシナリオがいくつかあり、以下に示すように、それらを安全にアンラップするさまざまな方法を使用できますが、常に十分な注意を払って使用する必要があります。


オプションを安全に処理するにはどうすればよいですか?

オプションに値が含まれているかどうかを確認する最も簡単な方法は、それをと比較することnilです。

if anOptionalInt != nil {
    print("Contains a value!")
} else {
    print("Doesn’t contain a value.")
}

ただし、オプションを使用する場合の99.9%の確率で、オプションが含まれている場合は、実際に含まれている値にアクセスする必要があります。これを行うには、オプションのバインディングを使用できます。

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

オプションのバインディングを使用すると、オプションに値が含まれているかどうかを確認でき、ラップされていない値を新しい変数または定数に割り当てることができます。バインド後に新しい変数の値を変更する必要があるかどうif let x = anOptional {...}if var x = anOptional {...}に応じて、構文またはを使用します。

例えば:

if let number = anOptionalInt {
    print("Contains a value! It is \(number)!")
} else {
    print("Doesn’t contain a number")
}

これは、最初にオプションに値が含まれていることを確認します。それは場合に行い、その後、「開封された」の値は、新しい変数(に割り当てられているnumber、それは非オプションであるかのようにあなたが自由に使用することができます- )。オプションに値が含まれていない場合は、予想どおり、else句が呼び出されます。

オプションのバインディングの優れている点は、複数のオプションを同時にアンラップできることです。ステートメントはコンマで区切ることができます。すべてのオプションがアンラップされている場合、ステートメントは成功します。

var anOptionalInt : Int?
var anOptionalString : String?

if let number = anOptionalInt, let text = anOptionalString {
    print("anOptionalInt contains a value: \(number). And so does anOptionalString, it’s: \(text)")
} else {
    print("One or more of the optionals don’t contain a value")
}

もう1つの巧妙なトリックは、値をアンラップした後、コンマを使用して値の特定の条件を確認できることです。

if let number = anOptionalInt, number > 0 {
    print("anOptionalInt contains a value: \(number), and it’s greater than zero!")
}

ifステートメント内でオプションのバインディングを使用する場合の唯一の欠点は、ステートメントのスコープ内からのみアンラップされた値にアクセスできることです。ステートメントの範囲外から値にアクセスする必要がある場合は、ガードステートメントを使用できます。

ガード文はあなたが成功するための条件を定義することができます-そしてその条件が満たされた場合、現在のスコープにのみ実行を継続します。それらは構文で定義されますguard condition else {...}

したがって、オプションのバインディングでそれらを使用するには、次のようにします。

guard let number = anOptionalInt else {
    return
}

(ガード本体内で、現在実行中のコードのスコープを終了するには、制御転送ステートメントの1つを使用する必要があることに注意してください)。

場合はanOptionalInt値が含まれ、それが開封され、新しいに割り当てられますnumber定数。その後、ガードののコードは実行を継続します。値が含まれていない場合、ガードは角かっこで囲まれたコードを実行します。これにより、制御が転送されるため、直後のコードは実行されません。

ガードステートメントの本当に素晴らしい点は、ラップされていない値がステートメントに続くコードで使用できるようになったことです(将来のコードはオプションに値がある場合にのみ実行できることがわかっているため)。これは、複数のifステートメントをネストすることによって作成された「運命のピラミッド」を排除するのに最適です。

例えば:

guard let number = anOptionalInt else {
    return
}

print("anOptionalInt contains a value, and it’s: \(number)!")

ガードは、複数のオプションを同時にアンラップしたり、where句を使用したりするなど、ifステートメントがサポートしたのと同じ巧妙なトリックもサポートします。

ifステートメントとguardステートメントのどちらを使用するかは、将来のコードでオプションに値を含める必要があるかどうかによって異なります。

ヌル合体演算子

無記号合体演算子の気の利いた簡略版である三条件演算子主として非optionalsとoptionalsを変換するために設計されました、。構文a ?? bはです。ここaで、はオプションの型でbあり、と同じ型ですa(ただし、通常はオプションではありません)。

基本的aに、「値が含まれている場合は、それをアンラップします。戻らない場合は、b代わりに」。たとえば、次のように使用できます。

let number = anOptionalInt ?? 0

これnumberにより、Int型の定数が定義されます。この定数には、値が含まれている場合はanOptionalInt、の値が含まれるか、そうでない場合が含まれ0ます。

これは、次の略記です。

let number = anOptionalInt != nil ? anOptionalInt! : 0

オプションのチェーン

オプションのチェーンを使用して、メソッドを呼び出したり、オプションのプロパティにアクセスしたりできます。これは、変数名を?使用するときに変数名の末尾にaを付けるだけで実行できます。

たとえばfoo、オプションのFooインスタンス型の変数があるとします。

var foo : Foo?

foo何も返さないメソッドを呼び出したい場合は、次のようにするだけです。

foo?.doSomethingInteresting()

場合はfoo値が含まれ、この方法は、それに呼び出されます。そうでない場合、悪いことは何も起こりません–コードは単に実行を続けます。

(これはnil、Objective-Cでメッセージを送信するのと同様の動作です)

したがって、これを使用してプロパティを設定したり、メソッドを呼び出したりすることもできます。例えば:

foo?.bar = Bar()

繰り返しますが、fooがあれば、ここで悪いことは何も起こりませんnil。コードは単に実行を継続します。

オプションのチェーンでできるもう1つの巧妙なトリックは、プロパティの設定またはメソッドの呼び出しが成功したかどうかを確認することです。これを行うには、戻り値をと比較しnilます。

(これは、何も返さないメソッドではVoid?なく、オプションの値が返されるためですVoid

例えば:

if (foo?.bar = Bar()) != nil {
    print("bar was set successfully")
} else {
    print("bar wasn’t set successfully")
}

ただし、プロパティにアクセスしたり、値を返すメソッドを呼び出そうとしたりすると、少し注意が必要になります。fooオプションであるため、そこから返されるものもすべてオプションになります。これに対処するには、上記のメソッドのいずれかを使用して返されるオプションをアンラップするか、メソッドfooにアクセスしたり、値を返すメソッドを呼び出す前に、それ自体をアンラップします。

また、名前が示すように、これらのステートメントを「チェーン」することができます。これは、プロパティを持つfooオプションのプロパティがある場合、次のように記述できることを意味します。bazqux

let optionalQux = foo?.baz?.qux

繰り返しますが、foobazはオプションであるため、から返される値は、それ自体がオプションquxであるかどうかに関係なく、常にquxオプションになります。

map そして flatMap

オプションでよく使用さmapれないflatMap機能は、and関数を使用する機能です。これらを使用すると、オプション以外の変換をオプションの変数に適用できます。オプションに値がある場合は、特定の変換を適用できます。値がない場合は、残りnilます。

たとえば、オプションの文字列があるとします。

let anOptionalString:String?

map関数をそれに適用することにより、関数を使用stringByAppendingStringして別の文字列に連結することができます。

stringByAppendingStringオプションではない文字列引数を取るため、オプションの文字列を直接入力することはできません。ただし、を使用mapすることにより、値があるstringByAppendingString場合に使用できるようにすることができanOptionalStringます。

例えば:

var anOptionalString:String? = "bar"

anOptionalString = anOptionalString.map {unwrappedString in
    return "foo".stringByAppendingString(unwrappedString)
}

print(anOptionalString) // Optional("foobar")

ただし、anOptionalString値がない場合は、mapを返しnilます。例えば:

var anOptionalString:String?

anOptionalString = anOptionalString.map {unwrappedString in
    return "foo".stringByAppendingString(unwrappedString)
}

print(anOptionalString) // nil

flatMapクロージャー本体内から別のオプションmapを返すことができることを除いて、と同様に機能します。つまり、オプション以外の入力を必要とするプロセスにオプションを入力できますが、オプション自体を出力することはできます。

try!

Swiftのエラー処理システムはDo-Try-Catchで安全に使用できます:

do {
    let result = try someThrowingFunc() 
} catch {
    print(error)
}

someThrowingFunc()エラーをスローした場合、エラーはcatchブロック内で安全にキャッチされます。

errorあなたが見一定のcatchブロックは、当社が宣言されていない-それは自動的にによって生成されますcatch

error自分自身を宣言することもできます。これには、次のような便利な形式にキャストできるという利点があります。

do {
    let result = try someThrowingFunc()    
} catch let error as NSError {
    print(error.debugDescription)
}

tryこの方法を使用することは、関数のスローに起因するエラーを試行、キャッチ、および処理するための適切な方法です。

try?エラーを吸収するものもあります:

if let result = try? someThrowingFunc() {
    // cool
} else {
    // handle the failure, but there's no error information available
}

しかし、Swiftのエラー処理システムは、次の方法で「強制的に試す」方法も提供しますtry!

let result = try! someThrowingFunc()

この投稿で説明されている概念はここにも当てはまります。エラーがスローされると、アプリケーションがクラッシュします。

try!その結果がコンテキストで失敗しないことを証明できる場合にのみ使用する必要があります。これは非常にまれです。

ほとんどの場合、完全なDo-Try-Catchシステムを使用しますtry?。エラーの処理が重要でないまれなケースでは、オプションのシステムを使用します。


リソース

65
Sajjon 2016-12-20 03:26.

TL; DR回答

非常に少数の例外、このルールは黄金です。

の使用を避ける !

?暗黙的にアンラップされたオプション(IUO)ではなく、変数オプション()を宣言します(!

言い換えれば、むしろ使用してください:
var nameOfDaughter: String?

の代わりに:
var nameOfDaughter: String!

if letまたはを使用してオプションの変数をアンラップしますguard let

次のように変数をアンラップします。

if let nameOfDaughter = nameOfDaughter {
    print("My daughters name is: \(nameOfDaughter)")
}

またはこのように:

guard let nameOfDaughter = nameOfDaughter else { return }
print("My daughters name is: \(nameOfDaughter)")

この回答は簡潔にすることを目的としており、完全に理解するために受け入れられた回答を読んでください


リソース

40
Duncan C 2016-02-29 04:37.

この質問は、最大来るALL THE TIME SO上。これは、新しいSwift開発者が最初に苦労することの1つです。

バックグラウンド:

Swiftは、「オプション」の概念を使用して、値を含む場合と含まない場合がある値を処理します。Cのような他の言語では、変数に値0を格納して、値が含まれていないことを示す場合があります。ただし、0が有効な値である場合はどうなりますか?次に、-1を使用できます。-1が有効な値である場合はどうなりますか?等々。

Swiftオプションを使用すると、有効な値を含めるか、値を含めないように、任意のタイプの変数を設定できます。

変数を意味するように宣言するとき(タイプx、または値なし)、タイプの後に疑問符を付けます。

オプションは、実際には、特定のタイプの変数を含むか、何も含まないコンテナです。

内部の値をフェッチするには、オプションを「ラップ解除」する必要があります。

「!」演算子は「強制アンラップ」演算子です。「私を信じてください。私が何をしているのか知っています。このコードが実行されるとき、変数にnilが含まれないことを保証します。」と書かれています。あなたが間違っているなら、あなたは墜落します。

自分が何をしているのか本当にわからない限り、「!」は避けてください。アンラップ演算子を強制します。これはおそらく、Swiftプログラマーを始めたばかりの人にとって最大のクラッシュの原因です。

オプションの扱い方:

より安全なオプションを処理する方法は他にもたくさんあります。ここにいくつかあります(完全なリストではありません)

「オプションのバインディング」または「iflet」を使用して、「このオプションに値が含まれている場合は、その値を新しい非オプションの変数に保存します。オプションに値が含まれていない場合は、このifステートメントの本文をスキップします。 "。

オプションのバインディングの例を次に示しfooます。

if let newFoo = foo //If let is called optional binding. {
  print("foo is not nil")
} else {
  print("foo is nil")
}

オプションの入札を使用するときに定義する変数は、ifステートメントの本体にのみ存在する(「スコープ内」にのみ存在する)ことに注意してください。

または、guardステートメントを使用して、変数がnilの場合に関数を終了することもできます。

func aFunc(foo: Int?) {
  guard let newFoo = input else { return }
  //For the rest of the function newFoo is a non-optional var
}

GuardステートメントはSwift2で追加されました。Guardを使用すると、コード全体で「ゴールデンパス」を保持し、「iflet」オプションのバインディングを使用することで発生することがあるネストされたifのレベルが増え続けるのを防ぐことができます。

「nil合体演算子」と呼ばれる構造もあります。「optional_var ?? replacement_val」の形式を取ります。オプションに含まれるデータと同じタイプの非オプション変数を返します。オプションにnilが含まれている場合、「??」の後に式の値を返します。シンボル。

したがって、次のようなコードを使用できます。

let newFoo = foo ?? "nil" // "??" is the nil coalescing operator
print("foo = \(newFoo)")

try / catchまたはguardエラー処理を使用することもできますが、通常、上記の他の手法の1つはよりクリーンです。

編集:

オプションを使用したもう1つの微妙な落とし穴は、「暗黙的にラップされていないオプションです。fooを宣言すると、次のようになります。

var foo: String!

その場合、fooはオプションですが、参照するためにラップを解除する必要はありません。つまり、fooを参照しようとすると、それがnilの場合はクラッシュします。

したがって、このコード:

var foo: String!


let upperFoo = foo.capitalizedString

fooを強制的にアンラップしていなくても、fooのcapitalizedStringプロパティを参照するとクラッシュします。印刷はきれいに見えますが、そうではありません。

したがって、暗黙的にアンラップされたオプションには本当に注意する必要があります。(そして、オプションをしっかりと理解するまでは、それらを完全に回避することもできます。)

結論:Swiftを初めて学習するときは、「!」のふりをしてください。文字は言語の一部ではありません。トラブルに巻き込まれる可能性があります。

13
Tharzeez 2017-11-18 06:15.

上記の回答は、オプションで安全にプレイする方法を明確に説明しているためです。オプションが本当に迅速に何であるかを説明しようとします。

オプションの変数を宣言する別の方法は

var i : Optional<Int>

そして、オプションタイプは2つのケースの列挙に他なりません。

 enum Optional<Wrapped> : ExpressibleByNilLiteral {
    case none 
    case some(Wrapped)
    .
    .
    .
}

したがって、変数 'i'にnilを割り当てます。できる var i = Optional<Int>.none か、値を割り当てるために、いくつかの値を渡します var i = Optional<Int>.some(28)

swiftによると、「nil」は価値の欠如です。そして、で初期化されたインスタンスを作成するnilと呼ばれるプロトコルに準拠しなければならない私たちにExpressibleByNilLiteral、あなたはそれを推測した場合、大きなだけOptionalsに準拠ExpressibleByNilLiteralして、他のタイプに適合することはお勧めできません。

ExpressibleByNilLiteralinit(nilLiteral:)instaceをnilで初期化するという単一のメソッドがあります。通常、このメソッドを呼び出すことはありません。迅速なドキュメントによると、オプションの型をnilリテラルで初期化するたびにコンパイラが呼び出すため、このイニシャライザを直接呼び出すことはお勧めしません。

私でさえ(しゃれを意図せずに)頭を包む必要があります。オプション:D Happy SwftingAll

12
QiunCheng 2016-07-30 21:18.

まず、オプションの値が何であるかを知っておく必要があります。あなたはにステップすることができスウィフトプログラミング言語の詳細について。

次に、オプションの値には2つのステータスがあることを知っておく必要があります。1つは完全な値で、もう1つはゼロ値です。したがって、オプションの値を実装する前に、それがどの状態であるかを確認する必要があります。

あなたは使用することができるif let ...guard let ... elseのように。

もう1つの方法は、実装前に変数の状態を確認したくない場合は、var buildingName = buildingName ?? "buildingName"代わりに使用することもできます。

8
Wissa 2018-04-14 04:06.

次のように、prepare for segueメソッドからOutlets値を設定しようとしたときに、このエラーが発生しました。

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let destination = segue.destination as? DestinationVC{

        if let item = sender as? DataItem{
            // This line pops up the error
            destination.nameLabel.text = item.name
        }
    }
}

次に、コントローラーがまだロードまたは初期化されていないため、宛先コントローラーのアウトレットの値を設定できないことがわかりました。

だから私はそれをこのように解決しました:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let destination = segue.destination as? DestinationVC{

        if let item = sender as? DataItem{
            // Created this method in the destination Controller to update its outlets after it's being initialized and loaded
            destination.updateView(itemData:  item)
        }
    }
}

宛先コントローラー:

// This variable to hold the data received to update the Label text after the VIEW DID LOAD
var name = ""

// Outlets
@IBOutlet weak var nameLabel: UILabel!

override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.
    nameLabel.text = name
}

func updateView(itemDate: ObjectModel) {
    name = itemDate.name
}

この回答が、マークされた回答がオプションとその機能を理解するための優れたリソースであることがわかったのと同じ問題を抱えている人に役立つことを願っていますが、問題自体には直接対処していません。

7
Cristik 2018-09-19 20:04.

基本的に、Swiftがnil以外の値のみを許可する場所でnil値を使用しようとしました。これは、コンパイラにnil値が存在しないことを信頼するように指示して、アプリをコンパイルできるようにすることです。

この種の致命的なエラーにつながるシナリオはいくつかあります。

  1. 強制アンラップ:

    let user = someVariable!
    

    someVariableがnilの場合、クラッシュします。強制アンラップを実行することで、nilチェックの責任をコンパイラーから自分に移しました。基本的に強制アンラップを実行することで、コンパイラーにnil値がないことを保証します。そして、どういうわけかnil値がで終わる場合に何が起こるかを推測しsomeVariableますか?

    解決?オプションのバインディング(別名if-let)を使用し、そこで変数処理を実行します。

    if user = someVariable {
        // do your stuff
    }
    
  2. 強制(ダウン)キャスト:

    let myRectangle = someShape as! Rectangle
    

    ここでは、強制的にキャストすることで、常にRectangleインスタンスが存在するため、コンパイラに心配しないように指示します。そしてそれが成り立つ限り、あなたは心配する必要はありません。問題は、プロジェクトのあなたまたはあなたの同僚が長方形以外の値を循環し始めたときに始まります。

    解決?オプションのバインディング(別名if-let)を使用し、そこで変数処理を実行します。

    if let myRectangle = someShape as? Rectangle {
        // yay, I have a rectangle
    }
    
  3. 暗黙的にアンラップされたオプション。次のクラス定義があると仮定しましょう。

    class User {
        var name: String!
    
        init() {
            name = "(unnamed)"
        }
    
        func nicerName() {
            return "Mr/Ms " + name
        }
    }
    

    これで、nameプロパティをに設定して誰もプロパティを台無しにしない場合nil、期待どおりに機能しUserますが、nameキーがないJSONから初期化された場合、プロパティを使用しようとすると致命的なエラーが発生します。

    解決?それらを使用しないでください:)プロパティが使用される必要があるときまでに常にnil以外の値を持つことが102%確実でない限り。ほとんどの場合、オプションまたは非オプションへの変換が機能します。これをオプション以外にすると、コンパイラは、見逃したコードパスにそのプロパティに値を指定することで、それを支援します。

  4. 接続されていない、またはまだ接続されていないコンセント。これはシナリオ#3の特定のケースです。基本的に、使用したいXIBロードクラスがいくつかあります。

    class SignInViewController: UIViewController {
    
        @IBOutlet var emailTextField: UITextField!
    }
    

    XIBエディターからコンセントへの接続を逃した場合、コンセントを使用するとすぐにアプリがクラッシュします。解決?すべてのコンセントが接続されていることを確認してください。または?、それらに演算子を使用しますemailTextField?.text = "[email protected]"。または、アウトレットをオプションとして宣言します。ただし、この場合、コンパイラーはコード全体でアウトレットをアンラップするように強制します。

  5. Objective-Cからの値であり、null可能性アノテーションがありません。次のObjective-Cクラスがあると仮定しましょう。

    @interface MyUser: NSObject
    @property NSString *name;
    @end
    

    これで、null可能性アノテーションが(明示的にまたはNS_ASSUME_NONNULL_BEGIN/を介してNS_ASSUME_NONNULL_END)指定されていない場合、nameプロパティはSwiftにString!(IUO-暗黙的にラップ解除されたオプション)としてインポートされます。一部の迅速なコードが値を使用するようになるとすぐに、nameがnilの場合はクラッシュします。

    解決?ヌル可能性アノテーションをObjective-Cコードに追加します。ただし、Objective-Cコンパイラは、null可能性に関しては少し寛容であり、明示的にnonnull。としてマークした場合でも、nil値になる可能性があることに注意してください。

2
Honey 2018-11-01 18:39.

これはもっと重要なコメントであり、nil値のデバッグに関しては、暗黙的にアンラップされたオプションが誤解を招く可能性がある理由です。

次のコードについて考えてみてください。エラー/警告なしでコンパイルされます。

c1.address.city = c3.address.city

ただし、実行時に次のエラーが発生します。致命的なエラー:オプション値のラップ解除中に予期せずnilが見つかりました

どのオブジェクトnilか教えていただけますか?

できません!

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

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        var c1 = NormalContact()
        let c3 = BadContact()

        c1.address.city = c3.address.city // compiler hides the truth from you and then you sudden get a crash
    }
}

struct NormalContact {
    var address : Address = Address(city: "defaultCity")
}

struct BadContact {
    var address : Address!
}

struct Address {
    var city : String
}

簡単に言うと、変数が他の読者からのものである可能性を隠しているというvar address : Address!ことです。そして、それがクラッシュしたとき、あなたは「一体何なの?!私はオプションではないのに、なぜ私はクラッシュするのですか?!」のようです。niladdress

したがって、次のように書くことをお勧めします。

c1.address.city = c2.address!.city  // ERROR:  Fatal error: Unexpectedly found nil while unwrapping an Optional value 

それがどのオブジェクトだったのnilか教えていただけますか?

今回は、コードがより明確になりました。あなたは合理化して、addressそれが強制的にアンラップされたパラメータである可能性が高いと考えることができます。

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

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        var c1 = NormalContact()
        let c2 = GoodContact()

        c1.address.city = c2.address!.city
        c1.address.city = c2.address?.city // not compile-able. No deceiving by the compiler
        c1.address.city = c2.address.city // not compile-able. No deceiving by the compiler
        if let city = c2.address?.city {  // safest approach. But that's not what I'm talking about here. 
            c1.address.city = city
        }

    }
}

struct NormalContact {
    var address : Address = Address(city: "defaultCity")
}

struct GoodContact {
    var address : Address?
}

struct Address {
    var city : String
}
2
Ale Mohamad 2019-05-21 07:34.

エラーはEXC_BAD_INSTRUCTIONfatal error: unexpectedly found nil while implicitly unwrapping an Optional valueを宣言した@IBOutletストーリーボードに接続していない場合に最も多く表示されます。

他の回答で言及されているように、オプションがどのように機能するかについても学ぶ必要がありますが、これは私に主に表示される唯一の時間です。

2
ShigaSuresh 2020-02-13 08:16.

CollectionViewでこのエラーが発生した場合は、CustomCellファイルとカスタムxibも作成してみてください。

mainVCのViewDidLoad()にこのコードを追加します。

    let nib = UINib(nibName: "CustomnibName", bundle: nil)
    self.collectionView.register(nib, forCellWithReuseIdentifier: "cell")
0
Mike Volmar 2019-09-27 05:11.

メインストーリーボードでビューコントローラーのカスタムクラス名を指定するのを忘れたため、テーブルビューコントローラーからビューコントローラーにセグエを作成しているときにこのエラーが発生しました。

他のすべてが問題ないように見えるかどうかを確認する価値のある単純なもの

Related questions

MORE COOL STUFF

Reba McEntire は、彼女が息子の Shelby Blackstock と共有する「楽しい」クリスマスの伝統を明らかにしました:「私たちはたくさん笑います」

Reba McEntire は、彼女が息子の Shelby Blackstock と共有する「楽しい」クリスマスの伝統を明らかにしました:「私たちはたくさん笑います」

Reba McEntire が息子の Shelby Blackstock と共有しているクリスマスの伝統について学びましょう。

メーガン・マークルは、自然な髪のスタイリングをめぐってマライア・キャリーと結ばれました

メーガン・マークルは、自然な髪のスタイリングをめぐってマライア・キャリーと結ばれました

メーガン・マークルとマライア・キャリーが自然な髪の上でどのように結合したかについて、メーガンの「アーキタイプ」ポッドキャストのエピソードで学びましょう.

ハリー王子は家族との関係を修復できるという「希望を持っている」:「彼は父親と兄弟を愛している」

ハリー王子は家族との関係を修復できるという「希望を持っている」:「彼は父親と兄弟を愛している」

ハリー王子が家族、特にチャールズ王とウィリアム王子との関係について望んでいると主張したある情報源を発見してください。

ワイノナ・ジャッドは、パニックに陥った休暇の瞬間に、彼女がジャッド家の家長であることを認識しました

ワイノナ・ジャッドは、パニックに陥った休暇の瞬間に、彼女がジャッド家の家長であることを認識しました

ワイノナ・ジャッドが、母親のナオミ・ジャッドが亡くなってから初めての感謝祭のお祝いを主催しているときに、彼女が今では家長であることをどのように認識したかを学びましょう.

セントヘレナのジェイコブのはしごを登るのは、気弱な人向けではありません

セントヘレナのジェイコブのはしごを登るのは、気弱な人向けではありません

セント ヘレナ島のジェイコブズ ラダーは 699 段の真っ直ぐ上る階段で、頂上に到達すると証明書が発行されるほどの難易度です。

The Secrets of Airline Travel Quiz

The Secrets of Airline Travel Quiz

Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

バイオニック読書はあなたをより速く読むことができますか?

バイオニック読書はあなたをより速く読むことができますか?

BionicReadingアプリの人気が爆発的に高まっています。しかし、それは本当にあなたを速読術にすることができますか?

スタートレックの50周年を称えるための最良の方法

スタートレックの50周年を称えるための最良の方法

来年は、スペースオペラの最も壮大で野心的なメディアシリーズの50周年を迎えます。しかし、スタートレックはその誇り高い遺産に沿って50歳の誕生日を迎えますか?スタートレックの誕生日を祝う方法はたくさんあります。

更新:合法的な大統領候補は数百万人を怒らせ、美しい女性は苦しむ

更新:合法的な大統領候補は数百万人を怒らせ、美しい女性は苦しむ

(画像提供:ゲッティイメージズ)ドナルド・トランプは、アメリカ合衆国大統領の立候補者となる比類のない外交的洞察力を示し、何百万人もの人々を怒らせ、彼の時代遅れの客体化に対する評価の主要な情報源を失いました。彼が立候補を発表し終える前にパレード。トランプ氏は演説の中で、この国で最も高い役職に選出された場合、米国との南の国境に壁を建設すると述べた一連の声明を発表した。

インターネット上で最も愚かな親ロシアのデマ

インターネット上で最も愚かな親ロシアのデマ

David L. Sternは、ウクライナのキエフを拠点とするフリーランスのライターです。

ディズニーフリークは今、独自の出会い系サイトを持っています

ディズニーフリークは今、独自の出会い系サイトを持っています

オンラインデートに関しては、船長、ベーコン愛好家、ポットヘッド向けに作られたサイトなど、長年にわたって選択できるニッチなサイトがたくさんあります。今、ディズニーファンは彼ら自身のマッチメイキングサイトを通して愛を見つけることができます。

米国のフィギュア スケートは、チーム イベントでの最終決定の欠如に「苛立ち」、公正な裁定を求める

米国のフィギュア スケートは、チーム イベントでの最終決定の欠如に「苛立ち」、公正な裁定を求める

ロシアのフィギュアスケーター、カミラ・バリエバが関与したドーピング事件が整理されているため、チームは2022年北京冬季オリンピックで獲得したメダルを待っています。

Amazonの買い物客は、わずか10ドルのシルクの枕カバーのおかげで、「甘やかされた赤ちゃんのように」眠れると言っています

Amazonの買い物客は、わずか10ドルのシルクの枕カバーのおかげで、「甘やかされた赤ちゃんのように」眠れると言っています

何千人ものAmazonの買い物客がMulberry Silk Pillowcaseを推奨しており、現在販売中. シルクの枕カバーにはいくつかの色があり、髪を柔らかく肌を透明に保ちます。Amazonで最大46%オフになっている間にシルクの枕カバーを購入してください

パデュー大学の教授が覚醒剤を扱った疑いで逮捕され、女性に性的好意を抱かせる

パデュー大学の教授が覚醒剤を扱った疑いで逮捕され、女性に性的好意を抱かせる

ラファイエット警察署は、「不審な男性が女性に近づいた」という複数の苦情を受けて、12 月にパデュー大学の教授の捜査を開始しました。

コンセプト ドリフト: AI にとって世界の変化は速すぎる

コンセプト ドリフト: AI にとって世界の変化は速すぎる

私たちの周りの世界と同じように、言語は常に変化しています。以前の時代では、言語の変化は数年または数十年にわたって発生していましたが、現在では数日または数時間で変化する可能性があります。

SF攻撃で91歳のアジア人女性が殴られ、コンクリートに叩きつけられた

犯罪擁護派のオークランドが暴力犯罪者のロミオ・ロレンゾ・パーハムを釈放

SF攻撃で91歳のアジア人女性が殴られ、コンクリートに叩きつけられた

認知症を患っている 91 歳のアジア人女性が最近、47 番街のアウター サンセット地区でロメオ ロレンゾ パーハムに襲われました。伝えられるところによると、被害者はサンフランシスコの通りを歩いていたところ、容疑者に近づき、攻撃を受け、暴行を受けました。

ℝ

“And a river went out of Eden to water the garden, and from thence it was parted and became into four heads” Genesis 2:10. ? The heart is located in the middle of the thoracic cavity, pointing eastward.

メリック・ガーランドはアメリカに失敗しましたか?

バイデン大統領の任期の半分以上です。メリック・ガーランドは何を待っていますか?

メリック・ガーランドはアメリカに失敗しましたか?

人々にチャンスを与えることは、人生で少し遅すぎると私は信じています。寛大に。

Language