仮定として、labelA
はUILabel
のインスタンスとしましょう。
なぜ、
if let x1 = Int(labelA.text!)
の所で、labelA.textの後に!が必要なのか分かりません。
Xcode 上で、text
の部分にマウスカーソルを持ってきて、optionを押しながらクリックしてください(もしくは、Cmd + クリックを実行し、Quick Helpを選択)。
すると、text
という変数(プロパティ)の型がポップアップで表示されます。
これをみると、text
の型がString?
型だということがわかります。
String?
型はString
型のオプショナル型という意味です。
オプショナル型とは、その変数に具体的な値が入っているか、もしくはnil
が入る型のことです。
一方、Int()
の引数としては、String?
型は受け付けていなくて、String
型である必要があります。
なので、String?
型をString
型に変換するための作業としてアンラップという処理が必要になります。アンラップを行う記号が!
というわけです。
エラーメッセージは
Value of optional type 'String?' must be unwrapped to a value of type 'String'
となっているはずですが、このメッセージはまさに上記のことを言っているわけです。
色々なサイトを調べると
let num = Int(label.text)!
のように、()の外に!があります。
はい、確かにInt()
の外に!
がある例があります(ない例もあります)。
これは、Quick Helpではすぐに出てきませんが、Quick Helpの下の方にある「Open in developer documntation`にそのヒントがあります。
上記の記述は
swift
1let num = Int.init(label.text)!
と同じ意味です(正確に理解するためには構造体のイニシャライザについて理解する必要がありますが、とりあえずそういうものだと思ってください)。
すると、Quick Help の下にあるリンクから開いた developer documentation から次のような行が発見できるはずです。
init?(String) Creates a new integer value from the given string.
これは、引数としてString
型を渡せば、それに対応した整数(Int
)型の値を返します、という意味になります。
ただし、気をつけなければいけないのは、init?
とここにも?
が出てきていることです(ちなみに、失敗のあるイニシャライザという言い方をします)。
どういうことかというと、返される値はオプショナル型だということです。Int()
に数字として変換するのに適した文字列が与えられれば良いのですが、必ずしもそのような場合とは限りません。例えば、Int("ABCDE")
という具合に到底数値には変換できない値が与えられた場合には、「変換できない」という状態を伝える必要があります。その手段としてnil
という特別な値が使われています。
このような理由から、Int()
にString型を与えたときには、Int
型ではなくてInt?
型(つまり、Int
型のオプショナル型)で返ってきます。
このままInt
型のオプショナル型として使い続ければ良い話なのですが、それだと不便(というか面倒)です。なので、Int?
型をInt
型として使うために、Int()
の外側に!
をつけてアンラップしています。
ちなみに、label
がUILabel
のインスタンスだったとしたら、上記の例ではエラーとなります。
エラーを出さないようにするためには、
swift
1let num = Int(label.text!)!
としなければいけません(最初の説明を思い出してください)。
ここから補足
ちなみに、上記の例は「あくまでもエラーを出さなくするため」の手段であって、末尾にも書いた通り、いろんな可能性を考えた場合、闇雲に!
をつけることは推奨できません(より適切な処理については、hoshi-takanoriさんによるこの回答へのコメントを参照してください)。
「より適切な処理」を理解するには、これはもうとにかく良質なコードを読んで参考にするか、適切な参考書を読んで理解を深めるか、自分でいろんなパターンを作って実験することで体得するしかないと、個人的には思っています。
補足終了
ここまできたら、ではなぜ
swift
1if let x1 = Int(labelA.text!) { //例1
なのに、一方では
swift
1let num = Int(labelA.text!)! //例2
となるのか疑問になると思います。例2
では最後に!
があるのに、例1
では!
がありません。
実は、例1
ではオプショナルバインディング(オプショナル束縛、if-let
文)という構文を用いているため、最後の!
を省けるという特例があります。
オプショナルバインディングは「オプショナル型の式の値がnil
ではなかった場合、その値をif
文のthen
節ですぐに使う」ための構文です(荻原剛志著・詳解Swift第5版99ページ)。
このように、オプショナル型だけでもいろいろな操作が絡んできます。太字にした文字はキーワードなので、より具体的には適切なオンラインドキュメント・書籍・Webページを調べてみてください。
最初のうちは大変なのですが、Swift、とりわけアプリを作る上ではオプショナル型の扱いは非常に重要になる上、適切に扱わないと(たとえば無闇に!
でアンラップすると)実行時エラーとなりドツボにハマることもあるので、しっかり抑えておくといいと思います。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/04/04 08:42
2020/04/04 08:56
2020/04/04 11:02