Swift IF LETはどのように評価されますか?


86

このコードはSwiftサイトやさまざまな投稿で見たことがあり、基本を理解しようとしています。この行はどのように評価されますか?

if let name = optionalName {

name ==オプションの名前ではなく、値を割り当てているので混乱しています。それでは、どのようにレポートがtrueになり、john appleseedをnilに置き換えても、それでも同じになるので、なぜtrueではないのでしょうか。

var optionalName: String? = "John Appleseed"
var greeting = "Hello!"
if let name = optionalName {
    greeting = "Hello, \(name)"
}

10
検索...スウィフトのマニュアルの「オプションの結合」
マーティン・R

3
dev.iachieved.it/iachievedit/?p=314でオプションを詳しく調べたところ、if let構文はオプションのバインディングとして知られています。
ジョー

回答:


100

基本的に、この行は、「新しい変数をnameオプション以外のバージョンと等しくすることができる場合はoptionalName、それを使用して次のことを行います」と言っています。Martinが指摘したように、これはオプションのバインディングと呼ばれます。

それの唯一の目的は、オプションの変数に実際の値が含まれているかどうかをテストし、オプションではないフォームを一時変数にバインドすることです。これは、オプションを「アンラップ」する、つまり、オプションに含まれる値にアクセスするための安全な方法です。それは決していかなる種類の平等をテストするものでもありません。オプション内の値の存在をテストするだけです。


1
私がそれに取り掛かるとき、私はそれを読むでしょう、私はちょうど速いイントロの始めに、そしてそれはそれを説明しません。あなたの説明は完全に理にかなっています、ありがとう。
DeadZero 2014

1
オプション変数の値が
-ifoptionalName

4
@Nuibbを使用if letする場合、値をオプション以外の変数(nameこの例では)にバインドするためです。と呼ばれる変数がないため、例はコンパイルされませんname。使用するoptionalNameように例を変更した場合は、として出力されHello, Optional("John Appleseed")ます。nilをチェックした後、強制アンラップを使用することもできますHello, \(optionalName!)が、コードのそのセクションをチェックせずにどこかに移動すると、エラーが発生しやすくなります。
ドレーヴァク2016年

29

オプションは設定されているか設定されていないか(nilまたはnilではない)...重要な決定を私たちに残します。「2つの両方の状態で正しく機能するように、コードをどのように作成する必要がありますか?」オプションをアンラップする方法は、私たちにとってそれを決定するものです。

設定されていないオプションに対抗するために使用できるいくつかのアプローチがあります。

  • クラッシュ!
  • 値が設定されていない場合は、デフォルトで値を設定します。
  • 優雅つまりは何もしない失敗するだけでなく、場合値が設定された、それを割り当てます。
  • 優雅つまりしかし、何もしない失敗した場合(それだけでより多くの単一代入以上です)値が設定された...何かをします。

以下は4つのアプローチです


値がない場合、強制アンラップを使用するとクラッシュします。その値を持つことが非常に重要である場合、たとえば映画タイトル(すべての映画には名前が必要です)の場合は、これを実行する必要があります。強制アンラップに使用されます。!

movieTitle = movie.title!

nil合体を使用することは、より詳細な制御を提供するもう1つの方法です。つまり、値が設定されていなくてもクラッシュせず、設定されていない場合は「何も設定されません」...指示どおりに実行されます。たとえば、名前が設定されていない場合、映画の名前はデフォルトでuntitled_movieに設定されます。??ヌル合体に使用されます。

var movieTitle = movie.title ?? "untitled_Movie"

オプションのチェーンを使用しても、値がない場合は何も実行されず、値がある場合は値が設定されます。これは、値を設定することが非常に重要ではないもの、たとえば俳優のエージェントの名前に対して行います?オプションのチェーンに使用されます。

let agent = movie.leadActor?.agent //would not crash if you don't have a lead actor (optional chaining)
let agent = movie.leadActor!.agent //would crash if you don't have a lead Actor (forced wrapping)  

使用するif-let(またはguard二つの異なるタイプである結合オプション)はあなたを与えるだろうより多くのコントロールが値が設定されていない場合は、それがクラッシュすることはありません。値が設定されている場合は、何かを行うことができます。設定されていない場合は、elseステートメントを追加できます。

if let supportingActor = movie.supportingActor{
print(" The supporting actor is \(supportingActor)}

強制的なアンラップはやや推奨されないため、これは最も一般的に使用されるアンラップの方法です。推奨されない理由の詳細については、こちらを参照してください。間の良好な比較のためguardif-letguard vs. if-let


サイドノート:

オプションのバインディングとオプションのチェーンは、一般的に一緒に使用されます。

if let agent = movie.leadActor?.agent {
ContactInfo = agent.phoneNumber
} // if-let is the optional *binding* part, the movie dot leadActor dot is the optional *chaining*
 

movieTitleが文字列以外のものになることは決してなく、すべての文字列がmovieTitleに有効である状況を考えると、強制的なアンラップが推奨されないのはなぜですか?(「無題の映画」は必要ありません。「」が必要です)この状況では、強制アンラップが唯一の正しい方法です。「強制アンラップはややお勧めできません」という部分を削除できれば、それは誤りです。 。
アンディ

ネットワークに電話をかけ、サーバーチームの開発者が悪い決定を下し、映画のタイトルを送信するのを忘れたとします。アプリを本番環境でクラッシュさせますか?それとも、不明なタイトルを書くだけですか?実際のところ、IMDbの一部の映画にはタイトルがありません:)。さらに、強制アンラップは、ロギングまたはアサートを行っていないことを意味します。それは良くないね。根本的な原因が何であるかわからないからです。
ハニー

それはストローマンの議論です、私は「常に強制的なアンラッピングを使用する」とは決して言いませんでした。例で強制アンラップを使用すべきではないからといって、すべての例で強制アンラップが推奨されないわけではありません。提示した4つのうち、強制アンラップが唯一の正しい解決策であるというシナリオを示しました。私の以前のコメントで述べたシナリオに対して、より良い解決策を提供できますか?そうでない場合は、コンテキストを考慮せずにやや落胆することはないため、「強制アンラップはやや推奨されません」に関するコメントを変更することを検討してください。
アンディ

デフォルトで「」に設定している場合、それはオプションではなくなります
Honey

たとえば、その「」値はストーリーボードで作成されたUILabelインスタンスのテキストプロパティから取得されます。動的に作成するとnilになる可能性があるためオプションですが、ここでは動的に作成しないため、常に文字列値が含まれます。 。この場合、強制アンラップを使用せず、代わりにif-letでアンラップし、デフォルト値 ""と同じ値を提供しますか?できますが、それは無意味で、不必要で、言葉遣いです。また、エラーが発生した場合でも常に辞書を返すHTTPライブラリを使用している場合はどうでしょうか。コンテキストに依存します。
アンディ

4

if構文は2つの異なる条件を受け入れます。2番目のオプションのバインディングはブール値ではありません。あなたが書くことができるように、これは混乱しています:

if let name = optionalName {

だがしかし

if (let name = optionalName) {

Appleのドキュメント(Swiftリファレンス):

条件の値は、タイプBoolまたはにブリッジされたタイプである必要がありますBoolオプションのバインディングで説明されているように、条件はオプションのバインディング宣言にすることもできます。


3

if エラーをスローする以外はブール式のみを取るため、このコードスニペットは次のように述べています。

if let name = optionalName {

}else{

}

optionalNameがnilの場合、条件はfalseであり、elseステートメントが実行されます。ただし、optionalNameに何らかの値がある場合、オプションの値は定数変数、つまりnameにアンラップ/割り当てられます。


1

弱参照、オプションの型を使用する場合は常に、コードを安全に保護し、クラッシュを回避するために使用する方がよいでしょう。ここに例を示します。

var middleName :String? = "some thing"
if let isExistsMiddleName = middleName {
// do some thing here
} else {
// no middle name
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.