[解決済み】「Fatal error: Unexpectedly found nil while unwrapping an Optional value "とはどういう意味ですか?
質問
Swiftのプログラムを書いたのですが、実行すると
EXC_BAD_INSTRUCTION
というエラーが表示されます。
Fatal error: Unexpectedly found nil while unwrapping an Optional value
も同様のエラーです。
Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
この投稿は、"予期せず nil" が見つかった問題に対する回答を収集することを目的としており、回答が散在して見つけにくくならないようにするためです。ご自由にご自身の答えを追加してください。 編集 既存のWikiの回答
解決方法は?
<上 この回答は コミュニティWiki . もし、より良いものになると思われるのであれば、遠慮なく 編集する !
背景 オプショナルとは?
Swiftでは
Optional<Wrapped>
は
オプションタイプ
この型は、元の型("Wrapped")から任意の値を含むことができ、また全く値を含まないこともできます(特殊な値である
nil
). オプションの値は
アンラップド
を使用することができます。
オプショナルは
汎用タイプ
ということになります。
Optional<Int>
と
Optional<String>
の中の型は、異なる型です。
<>
をWrapped型と呼びます。オプションは、その内部では
列挙
の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 :
<ブロッククオート
Swiftは
タイプセーフ
つまり、コードが扱うことのできる値の種類を明確にすることができる言語なのです。もしあなたのコードの一部が
String
を渡すと、型安全性により
Int
を誤って
同様に、型安全性により、誤ってオプションの
String
を必要とするコードに、オプションでない
String
.
型安全性は、開発プロセスのできるだけ早い段階でエラーを発見し、修正するのに役立ちます。
他のプログラミング言語にも、汎用的な オプションタイプ : 例えば たぶん をHaskellで表現しています。 オプション はRustで、そして オプショナル C++17では
プログラミング言語では
なし
オプションタイプでは、特定の
センチネル値
は、有効な値がないことを示すためによく使われる。Objective-Cでは、例えば。
nil
(その
ヌルポインター
) は、オブジェクトの欠如を表します。のような原始的な型では
int
NULLポインターは使えないので、別の変数(例えば
value: Int
と
isValid: Bool
) または指定されたセンチネル値 (例えば
-1
または
INT_MIN
). このような方法では
isValid
またはセンチネル値をチェックする必要があります。また、特定の値がセンチネルとして選択された場合、それはもはや
有効な
の値です。
のようなオプションタイプは、Swiftの
Optional
はこれらの問題を解決するために、特別な別の
nil
また、強い型システムを利用して、必要なときに nil をチェックすることをコンパイラが覚えてくれるようにします。
なぜ、" 致命的なエラーです。Optional 値のアンラップ中に予期せず nil が見つかりました。 "?
オプショナルの値にアクセスするには (値がある場合)、次のようにする必要があります。 アンラップ です。オプショナルな値は、安全に、あるいは強制的にアンラップすることができます。もしオプショナルを強制的にアンラップして はなかった が値を持つと、上記のようなメッセージが表示され、プログラムがクラッシュします。
Xcodeは、コードの行をハイライトすることでクラッシュを表示します。問題はこの行で発生します。
このクラッシュは、2種類のforce-unwrapで発生する可能性があります。
1. 明示的なフォースアラップ
これを行うには
!
演算子をオプションで使用します。例えば
let anOptionalString: String?
print(anOptionalString!) // <- CRASH
致命的なエラーです。Optional値のアンラップ中に予期せずnilが見つかりました。
として
anOptionalString
は
nil
で、強制的にアンラップした行でクラッシュします。
2. 暗黙のうちにアンラップされるオプショナルツール
これらは
!
ではなく
?
の後に、型が表示されます。
var optionalDouble: Double! // this value is implicitly unwrapped wherever it's used
これらのオプショナルは、値を含むことが前提となっています。したがって、暗黙的にアンラップされたオプショナルにアクセスするときはいつでも、それは自動的に強制的にアンラップされることになります。もし、値が含まれていなければ、クラッシュします。
print(optionalDouble) // <- CRASH
致命的なエラーです。予期しない nil が見つかりました。 暗黙のうちに Optional 値のアンラップ
どの変数がクラッシュを引き起こしたかを調べるには、以下のようにします。 ⌥ をクリックすると定義が表示され、そこにオプションの型が表示されるかもしれません。
特にIBOutletsは、通常、暗黙的にラップされていないオプショナルである。これは、xibやストーリーボードが実行時にアウトレットをリンクするためである。
後
を初期化します。したがって、ロードされる前にアウトレットにアクセスすることがないようにする必要があります。また、storyboard/xibファイルで接続が正しいかどうかを確認する必要があります。
nil
を実行すると、暗黙のうちにアンラップされ、クラッシュします。接続を修正する場合は、アウトレットを定義しているコード行を削除し、再接続してみてください。
Optionalの強制アンラップはどのような場合に行うべきですか?
明示的な強制アンラップ
一般的なルールとして、オプショナルを強制的にアンラップするために
!
演算子を使用します。を使用する場合があります。
!
しかし、このオプションが値を含んでいることが100%確実な場合にのみ使用すべきです。
がある一方で かもしれません。 のように、強制アンラップが使える場合があります。 事実 オプショナルに値が含まれていること、つまり シングル その代わりに、そのオプショナルを安全にアンラップできない場所です。
暗黙のうちにアンラップされるオプショナルツール
これらの変数は、コードの後半まで代入を先延ばしできるように設計されています。それは あなたの アクセスする前に、値があることを確認する責任があります。しかし、これらはフォース・アンラップを含むため、本質的に安全ではありません。 を想定しています。 nilを代入することは有効ですが、その値はnil以外です。
暗黙のうちにアンラップされたオプショナルは、あくまでも 最後の手段 . を使用できる場合は 遅延変数 を提供するか、あるいは デフォルト値 を使用する場合は、暗黙のうちにアンラップされたオプショナルを使用するのではなく、そうする必要があります。
ただし 暗黙のうちにアンラップされたオプショナルが有益であるいくつかのシナリオ また、以下のように安全にアンラップするための様々な方法を使用することができます。 常に 十分な注意を払いながら使用してください。
Optionalを安全に扱うには?
オプショナルに値が含まれているかどうかを確認する最も簡単な方法は、その値を
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")
}
もう一つの巧妙なトリックは、ラップを解いた後、カンマを使って値に対してある条件をチェックすることもできる。
if let number = anOptionalInt, number > 0 {
print("anOptionalInt contains a value: \(number), and it’s greater than zero!")
}
if文の中でオプショナルバインディングを使うと、ラップされていない値にはその文の範囲内からしかアクセスできないのが唯一の欠点です。もしステートメントのスコープ外から値にアクセスする必要がある場合は、if文の中で ガード文 .
A
ガードステートメント
この条件を満たす場合にのみ、現在のスコープが実行を継続します。これは次の構文で定義します。
guard condition else {...}
.
そこで、オプショナルバインディングで使用するには、次のようにします。
guard let number = anOptionalInt else {
return
}
(なお、ガード本体内では は のいずれかを使用します。 制御伝達文 現在実行中のコードのスコープを抜けるため)。
もし
anOptionalInt
が値を含んでいる場合、その値はラップされずに新しい
number
の定数です。コード
後
の場合、ガードの実行は継続されます。もし値が含まれていなければ、ガードは括弧内のコードを実行し、制御の移行を行い、直後のコードは実行されません。
ガード文の優れた点は、ラップされていない値を、その文に続くコードで使用できることです。 のみ が値を持つ場合に実行されます)。これは '運命のピラミッド' 複数のif文のネストによって発生します。
例えば
guard let number = anOptionalInt else {
return
}
print("anOptionalInt contains a value, and it’s: \(number)!")
ガードは、if 文がサポートしていたのと同じ巧妙なトリックもサポートしています。
where
節があります。
if文とguard文のどちらを使用するかは、将来のコードが が必要です。 が値を含んでいることを確認します。
Nil Coalescing オペレータ
は
Nil Coalescing Operator(ニル・コアレスティング・オペレーター
の便利な略記版です。
三項条件演算子
主にオプショナルをノン・オプショナルに変換するために設計されています。これは,次のような構文になります。
a ?? b
ここで
a
はオプションの型であり
b
と同じ型です。
a
(通常は非オプショナルですが)。
これは、基本的に「もし
a
が値を含んでいる場合、それをアンラップします。そうでない場合は
b
代わりに "です。例えば、こんな使い方ができます。
let number = anOptionalInt ?? 0
これは
number
の定数
Int
型の値を含む。
anOptionalInt
値を含む場合、または
0
を指定します。
の略語に過ぎない。
let number = anOptionalInt != nil ? anOptionalInt! : 0
オプショナル・チェイニング
を使用することができます。
オプショナル・チェーニング
を使用すると、オプショナルメソッドを呼び出したりプロパティにアクセスしたりすることができます。これは、変数名の末尾に
?
を使用します。
例えば、変数
foo
で、タイプはオプションの
Foo
のインスタンスです。
var foo : Foo?
のメソッドを呼び出したい場合
foo
何も返さないのであれば、単純にそうすることができます。
foo?.doSomethingInteresting()
もし
foo
が値を含んでいれば、その値に対してこのメソッドが呼ばれます。もし値がなければ、何も悪いことは起こらず、コードは単に実行を継続します。
(にメッセージを送信するのと同様の動作です)。
nil
Objective-Cの場合)
したがって、これはメソッドを呼び出すだけでなく、プロパティを設定するためにも使用することができます。例えば
foo?.bar = Bar()
ここでも、以下のようにすれば、何も悪いことは起こりません。
foo
は
nil
. あなたのコードは単に実行し続けるだけです。
オプショナルチェーンでできるもうひとつの技は、プロパティの設定やメソッドの呼び出しがうまくいったかどうかをチェックすることです。これを行うには、返り値を
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
関数があります。これらは、オプショナルな変数にオプショナルではない変換を適用するためのものです。オプショナル変数が値を持つ場合、指定した変換を適用することができます。値を持たない場合は、そのまま
nil
.
例えば、オプションの文字列があるとします。
let anOptionalString:String?
を適用することで
map
関数を使用することができます。
stringByAppendingString
関数を使って、別の文字列に連結することができます。
なぜなら
stringByAppendingString
は非オプションの文字列を引数に取るので、オプションの文字列を直接入力することはできません。しかし
map
を使用すると、allow
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 {
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のエラー処理システムは、quot;force try"する方法も提供しています。
try!
:
let result = try! someThrowingFunc()
この記事で説明したコンセプトはここでも適用されます。エラーがスローされると、アプリケーションはクラッシュします。
のみを使用する必要があります。
try!
その結果があなたのコンテキストで決して失敗しないことを証明できる場合 - そしてこれは非常に稀なことです。
ほとんどの場合、完全なDo-Try-Catchシステム、およびオプションのシステムを使用することになるでしょう。
try?
を、エラーの処理が重要でない稀なケースで使用します。
リソース
関連
-
パスワード入力を非表示にする InstallShield スクリプト
-
[解決済み】 mean() 警告:引数が数値または論理でない:NAを返す
-
[解決済み】警告メッセージ。In `...` : invalid factor level, NA generated 警告メッセージ:...`は無効な因子レベルです。
-
[解決済み】C++エラー: 予想されるunqualified-idを修正する方法
-
[解決済み】主成分分析:colMeans(x, na.rm = TRUE)のエラー:'x'は数値でなければなりません。
-
[解決済み】constで変数を初期化しようとすると「initializerの要素が定数でない」というエラーが発生する。
-
[解決済み】必要な形式パラメータに対応する引数が与えられない - .NETエラー
-
[解決済み】ウィンドウ階層にないビューを持つUIViewControllerでUIViewControllerを表示しようとする
-
[解決済み】行列式で「数値/複雑な行列/ベクトルの引数が必要です」というエラーが発生?
-
[解決済み】Heroku + node.jsのエラー(Webプロセスが起動後60秒以内に$PORTにバインドできなかった)。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Swift言語とAppleScriptの違い、AppleScriptの開発状況について教えてください。
-
InstallShield で IIS がインストールされているかどうかを検出するスクリプト
-
LinuxでRの新バージョンを直接コピーする方法
-
[解決済み】R: predict() で数値 'envir' 引数が長さ1でない。)
-
[解決済み】C++の<map>に相当するC#は何ですか?[重複しています]
-
[解決済み】Looper.prepare()を呼び出していないスレッド内でハンドラを作成できない。)
-
[解決済み】データフレームで関数を適用する場合、dim(X)は正の長さでなければならない
-
[解決済み】マージが終了していない(MERGE_HEADが存在する)。
-
[解決済み】エラー。式はintegralまたはunscoped enum型でなければなりません。
-
[解決済み】ポインタと整数の比較を警告する