teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

2

検証コードを追加し、説明文の記述を改めました。

2020/01/01 12:39

投稿

eytyet
eytyet

スコア803

answer CHANGED
@@ -1,10 +1,26 @@
1
+ 検証コードを作成してみました。以下をplaygroundで実行すると、それぞれの型が確認できます。
2
+
3
+ ```swift
4
+ let image: UIImage? = UIImage(systemName: "icloud")
5
+ let a = (image?.jpegData(compressionQuality: 1))!
6
+ let b = image?.jpegData(compressionQuality: 1)!
7
+ print("Type of a =", type(of: a)) // Type of a = Data
8
+ print("Type of b =", type(of: b)) // Type of b = Optional<Data>
9
+ ```
10
+
11
+ ということで、
1
12
  `(userProfileImageView.image?.jpegData(compressionQuality: 0.01))!`
2
13
  の型は`Data`型です。
3
-
4
14
  `userProfileImageView.image?.jpegData(compressionQuality: 0.01)!`
5
15
  の型は、`Data?`型です。
6
16
 
7
- 括弧をつけない場合`!`が`jpegData()`値に対して適用されます。
17
+ 括弧をつけるかつけないかで評価結果が異なります。
8
- `userProfileImageView.image?`のアンラップに失敗したら`nil`になり、成功したらその後ろが評価されて関数の戻り値である`Data?`型が`!`で強制アンラップされて`Data`が返されます。最初のアンラップの失敗は起こりませんが、論理的に可能性があるため、戻り値がnilとDataの2種類あるため、最終的な戻り値が`Data?`型になるみたいです。
9
18
 
10
- 括弧をつけると、`!`が`userProfileImageView.image?`と`jpegData()`の戻り値の両方に対して適用されます。最初のアンラップに失敗したら!で強制終了です(ifで確認しているのでこれは発生しません)成功たら、その後ろが評価されて関数戻り値である`Data?`型が`!`で強制アンラップされ`Data`になるので、最終的な戻が`Data`型になります。
19
+ 前者の括弧をつけた方は、`!`が一番最後に適用されます。まず`userProfileImageView.image?`が評価されます。これnilでない事はif保証されているので成功しまその後ろが評価されて、`jpegData()`関数が呼ばれ、戻り値である`Data?`型が得られます。つまり括弧の中の評価結果は`Data?`です。これに対して、`!`で強制アンラップが実行されます。nilだったら強制終了します。nilじゃなかったら、`Data`が結果になります。したって、式の結果は`Data`型す。
20
+
21
+ 後者の括弧をつけない場合、`!`が`jpegData()`の戻り値に対してだけ適用されます。
22
+ `userProfileImageView.image?`のアンラップに失敗したら評価結果は`nil`になり、そこで終了です。その後ろは評価されません。しかし、if文のおかげでここでは成功するので、その後ろが評価されて`jpegData()`関数が呼ばれ、その戻り値は`Data?`です。これが強制アンラップされて、`nil`なら強制終了し、`nil`でないなら`Data`になります。
23
+ ifがあるので最初のアンラップの失敗は起こりませんが、式としては発生し得るため、式の評価結果は`nil`と`Data`の2種類があることになり、最終的に`Data?`型になるようです。
24
+
25
+ ?と!は演算子ではないそうで、単純な式のように見えても内部では複雑な事をしているようですね。
26
+ `UIImage?`型である`userProfileImageView.image?`がnilである場合と、`Data?`をアンラップした`Data`型とが組み合わされて`Data?`になるのは驚きました。もしかしたら、何か私が誤解しているのかもしれません。解釈が間違っていたら、どなたかご指摘いただけると幸いです。

1

回答が完全に間違っていたので書き直しました。

2020/01/01 12:39

投稿

eytyet
eytyet

スコア803

answer CHANGED
@@ -1,7 +1,10 @@
1
+ `(userProfileImageView.image?.jpegData(compressionQuality: 0.01))!`
1
- カッコ有無による違いないと思います。
2
+ `Data`型です。
2
- 強いていえば、ビルド時間がナノ秒単位で伸びるかもしれませんが。
3
- swiftの括弧の機能は、評価の優先順位を変更する事と、関数を呼び出す事で、他にはないと思います。今回の場合は前者の括弧なので、有無による機能的な差は無いです。
4
- ただ、読みやすくなっていると思う人もいるかもしれませんね。
5
- おそらく、これを書いた人は、オプショナルをアンラップするのを括弧の中が全部終わってからやる、ということを明示的に示したかったのではないでしょうか。この括弧の中には、二つオプショナルがあるので、どっちもまとめて強制的にアンラップする、ということを間違いなく記述したかったのかなと想像します。
6
3
 
7
- 優先順位が曖昧なものに対して、無くても良い括弧をつける事は、可読性を高める良い事だと考える人々も多くいるので、必要ないから間違いという訳でもありません。
4
+ `userProfileImageView.image?.jpegData(compressionQuality: 0.01)!`
5
+ の型は、`Data?`型です。
6
+
7
+ 括弧をつけない場合、`!`が`jpegData()`の戻り値に対して適用されます。
8
+ `userProfileImageView.image?`のアンラップに失敗したら`nil`になり、成功したらその後ろが評価されて関数の戻り値である`Data?`型が`!`で強制アンラップされて`Data`が返されます。最初のアンラップの失敗は起こりませんが、論理的に可能性があるため、戻り値がnilとDataの2種類あるため、最終的な戻り値が`Data?`型になるみたいです。
9
+
10
+ 括弧をつけると、`!`が`userProfileImageView.image?`と`jpegData()`の戻り値の両方に対して適用されます。最初のアンラップに失敗したら!で強制終了です(が、ifで確認しているのでこれは発生しません)。成功したら、その後ろが評価されて関数の戻り値である`Data?`型が`!`で強制アンラップされて`Data`になるので、最終的な戻り値が`Data`型になります。