私のSwiftプログラムはEXC_BAD_INSTRUCTION
、次のいずれかの同様のエラーでクラッシュします。このエラーはどういう意味ですか、どうすれば修正できますか?
致命的なエラー:オプション値のアンラップ中に予期せずnilが見つかりました
または
致命的なエラー:オプションの値を暗黙的にアンラップしているときに、予期せずnilが見つかりました
この投稿は、「予期せず見つかったnil」の問題に対する回答を収集することを目的としているため、それらが散在して見つけにくいものではありません。独自の回答を追加するか、既存のWiki回答を編集してください。
この答えは「コミュニティ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では、nil
(nullポインタ)はオブジェクトがないことを表します。以下のようなプリミティブ型の場合はint
、あなたが別の変数(のようないずれかの必要がありますので、ヌルポインタが、使用できないvalue: Int
とisValid: Bool
)、または指定されたセンチネル値を(など-1
かINT_MIN
)。これらのアプローチはisValid
、番兵の値を確認したり確認したりするのを忘れがちなため、エラーが発生しやすくなります。また、特定の値が番兵として選択された場合、それは有効な値として扱われなくなることを意味します。
SwiftなどのオプションタイプはOptional
、特別な個別のnil
値を導入し(したがって、番兵の値を指定する必要がない)、強力な型システムを活用することでこれらの問題を解決します。これにより、コンパイラーは、必要に応じてnilを忘れずにチェックできます。
オプションの値にアクセスするには(オプションがある場合)、それをアンラップする必要があります。オプションの値は、安全または強制的にアンラップできます。オプションを強制的にアンラップし、値がなかった場合、プログラムは上記のメッセージでクラッシュします。
Xcodeは、コード行を強調表示することでクラッシュを表示します。この行で問題が発生します。
このクラッシュは、2種類の強制アンラップで発生する可能性があります。
これは!
、オプションのオペレーターで行われます。例えば:
let anOptionalString: String?
print(anOptionalString!) // <- CRASH
致命的なエラー:オプション値のアンラップ中に予期せずnilが見つかりました
以下のようanOptionalString
であるnil
ここで、あなたはそれアンラップ強制ライン上でクラッシュを取得します。
これらは、タイプの後では!
なく、で定義され?
ます。
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
オプションのプロパティがある場合、次のように記述できることを意味します。baz
qux
let optionalQux = foo?.baz?.qux
繰り返しますが、foo
とbaz
はオプションであるため、から返される値は、それ自体がオプション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?
。エラーの処理が重要でないまれなケースでは、オプションのシステムを使用します。
非常に少数の例外、このルールは黄金です。
!
?
暗黙的にアンラップされたオプション(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)")
この回答は簡潔にすることを目的としており、完全に理解するために受け入れられた回答を読んでください
この質問は、最大来る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を初めて学習するときは、「!」のふりをしてください。文字は言語の一部ではありません。トラブルに巻き込まれる可能性があります。
上記の回答は、オプションで安全にプレイする方法を明確に説明しているためです。オプションが本当に迅速に何であるかを説明しようとします。
オプションの変数を宣言する別の方法は
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
して、他のタイプに適合することはお勧めできません。
ExpressibleByNilLiteral
init(nilLiteral:)
instaceをnilで初期化するという単一のメソッドがあります。通常、このメソッドを呼び出すことはありません。迅速なドキュメントによると、オプションの型をnil
リテラルで初期化するたびにコンパイラが呼び出すため、このイニシャライザを直接呼び出すことはお勧めしません。
私でさえ(しゃれを意図せずに)頭を包む必要があります。オプション:D Happy SwftingAll。
まず、オプションの値が何であるかを知っておく必要があります。あなたはにステップすることができスウィフトプログラミング言語の詳細について。
次に、オプションの値には2つのステータスがあることを知っておく必要があります。1つは完全な値で、もう1つはゼロ値です。したがって、オプションの値を実装する前に、それがどの状態であるかを確認する必要があります。
あなたは使用することができるif let ...
かguard let ... else
のように。
もう1つの方法は、実装前に変数の状態を確認したくない場合は、var buildingName = buildingName ?? "buildingName"
代わりに使用することもできます。
次のように、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
}
この回答が、マークされた回答がオプションとその機能を理解するための優れたリソースであることがわかったのと同じ問題を抱えている人に役立つことを願っていますが、問題自体には直接対処していません。
基本的に、Swiftがnil以外の値のみを許可する場所でnil値を使用しようとしました。これは、コンパイラにnil値が存在しないことを信頼するように指示して、アプリをコンパイルできるようにすることです。
この種の致命的なエラーにつながるシナリオはいくつかあります。
強制アンラップ:
let user = someVariable!
someVariable
がnilの場合、クラッシュします。強制アンラップを実行することで、nilチェックの責任をコンパイラーから自分に移しました。基本的に強制アンラップを実行することで、コンパイラーにnil値がないことを保証します。そして、どういうわけかnil値がで終わる場合に何が起こるかを推測しsomeVariable
ますか?
解決?オプションのバインディング(別名if-let)を使用し、そこで変数処理を実行します。
if user = someVariable {
// do your stuff
}
強制(ダウン)キャスト:
let myRectangle = someShape as! Rectangle
ここでは、強制的にキャストすることで、常にRectangle
インスタンスが存在するため、コンパイラに心配しないように指示します。そしてそれが成り立つ限り、あなたは心配する必要はありません。問題は、プロジェクトのあなたまたはあなたの同僚が長方形以外の値を循環し始めたときに始まります。
解決?オプションのバインディング(別名if-let)を使用し、そこで変数処理を実行します。
if let myRectangle = someShape as? Rectangle {
// yay, I have a rectangle
}
暗黙的にアンラップされたオプション。次のクラス定義があると仮定しましょう。
class User {
var name: String!
init() {
name = "(unnamed)"
}
func nicerName() {
return "Mr/Ms " + name
}
}
これで、name
プロパティをに設定して誰もプロパティを台無しにしない場合nil
、期待どおりに機能しUser
ますが、name
キーがないJSONから初期化された場合、プロパティを使用しようとすると致命的なエラーが発生します。
解決?それらを使用しないでください:)プロパティが使用される必要があるときまでに常にnil以外の値を持つことが102%確実でない限り。ほとんどの場合、オプションまたは非オプションへの変換が機能します。これをオプション以外にすると、コンパイラは、見逃したコードパスにそのプロパティに値を指定することで、それを支援します。
接続されていない、またはまだ接続されていないコンセント。これはシナリオ#3の特定のケースです。基本的に、使用したいXIBロードクラスがいくつかあります。
class SignInViewController: UIViewController {
@IBOutlet var emailTextField: UITextField!
}
XIBエディターからコンセントへの接続を逃した場合、コンセントを使用するとすぐにアプリがクラッシュします。解決?すべてのコンセントが接続されていることを確認してください。または?
、それらに演算子を使用しますemailTextField?.text = "[email protected]"
。または、アウトレットをオプションとして宣言します。ただし、この場合、コンパイラーはコード全体でアウトレットをアンラップするように強制します。
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値になる可能性があることに注意してください。
これはもっと重要なコメントであり、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!
ことです。そして、それがクラッシュしたとき、あなたは「一体何なの?!私はオプションではないのに、なぜ私はクラッシュするのですか?!」のようです。nil
address
したがって、次のように書くことをお勧めします。
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
}
エラーはEXC_BAD_INSTRUCTION
、fatal error: unexpectedly found nil while implicitly unwrapping an Optional value
を宣言した@IBOutlet
がストーリーボードに接続していない場合に最も多く表示されます。
他の回答で言及されているように、オプションがどのように機能するかについても学ぶ必要がありますが、これは私に主に表示される唯一の時間です。
CollectionViewでこのエラーが発生した場合は、CustomCellファイルとカスタムxibも作成してみてください。
mainVCのViewDidLoad()にこのコードを追加します。
let nib = UINib(nibName: "CustomnibName", bundle: nil)
self.collectionView.register(nib, forCellWithReuseIdentifier: "cell")
メインストーリーボードでビューコントローラーのカスタムクラス名を指定するのを忘れたため、テーブルビューコントローラーからビューコントローラーにセグエを作成しているときにこのエラーが発生しました。
他のすべてが問題ないように見えるかどうかを確認する価値のある単純なもの
Reba McEntire が息子の Shelby Blackstock と共有しているクリスマスの伝統について学びましょう。
メーガン・マークルとマライア・キャリーが自然な髪の上でどのように結合したかについて、メーガンの「アーキタイプ」ポッドキャストのエピソードで学びましょう.
ハリー王子が家族、特にチャールズ王とウィリアム王子との関係について望んでいると主張したある情報源を発見してください。
ワイノナ・ジャッドが、母親のナオミ・ジャッドが亡くなってから初めての感謝祭のお祝いを主催しているときに、彼女が今では家長であることをどのように認識したかを学びましょう.
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?
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!
来年は、スペースオペラの最も壮大で野心的なメディアシリーズの50周年を迎えます。しかし、スタートレックはその誇り高い遺産に沿って50歳の誕生日を迎えますか?スタートレックの誕生日を祝う方法はたくさんあります。
(画像提供:ゲッティイメージズ)ドナルド・トランプは、アメリカ合衆国大統領の立候補者となる比類のない外交的洞察力を示し、何百万人もの人々を怒らせ、彼の時代遅れの客体化に対する評価の主要な情報源を失いました。彼が立候補を発表し終える前にパレード。トランプ氏は演説の中で、この国で最も高い役職に選出された場合、米国との南の国境に壁を建設すると述べた一連の声明を発表した。
オンラインデートに関しては、船長、ベーコン愛好家、ポットヘッド向けに作られたサイトなど、長年にわたって選択できるニッチなサイトがたくさんあります。今、ディズニーファンは彼ら自身のマッチメイキングサイトを通して愛を見つけることができます。
ロシアのフィギュアスケーター、カミラ・バリエバが関与したドーピング事件が整理されているため、チームは2022年北京冬季オリンピックで獲得したメダルを待っています。
何千人ものAmazonの買い物客がMulberry Silk Pillowcaseを推奨しており、現在販売中. シルクの枕カバーにはいくつかの色があり、髪を柔らかく肌を透明に保ちます。Amazonで最大46%オフになっている間にシルクの枕カバーを購入してください
ラファイエット警察署は、「不審な男性が女性に近づいた」という複数の苦情を受けて、12 月にパデュー大学の教授の捜査を開始しました。
私たちの周りの世界と同じように、言語は常に変化しています。以前の時代では、言語の変化は数年または数十年にわたって発生していましたが、現在では数日または数時間で変化する可能性があります。
認知症を患っている 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.
人々にチャンスを与えることは、人生で少し遅すぎると私は信じています。寛大に。