読者です 読者をやめる 読者になる 読者になる

Swiftで遊ぼう! on Hatena

あしたさぬきblogでやってた初心者オヤジのiOSプログラミング奮闘記がHatenaに来ました

Swiftで遊ぼう! - 657 - contextが組み込まれたviewを設定する

次のTable Viewのチュートリアルを拡張しています。

yataiblue.hatenablog.com

「snapshotOfCell()」の内容を詳しくみている途中でした。

func snapshotOfCell(inputView: UIView) -> UIView {
  UIGraphicsBeginImageContextWithOptions(inputView.bounds.size, 
                           false, 0.0)
  let context = UIGraphicsGetCurrentContext()!
  inputView.layer.renderInContext(context)
  let image = UIGraphicsGetImageFromCurrentImageContext() as UIImage
  UIGraphicsEndImageContext()
        
  let cellSnapshot : UIView = UIImageView(image: image)
  cellSnapshot.layer.masksToBounds = false
  cellSnapshot.layer.cornerRadius = 0.0
  cellSnapshot.layer.shadowOffset = CGSizeMake(-5.0, 0.0)
  cellSnapshot.layer.shadowRadius = 5.0
  cellSnapshot.layer.shadowOpacity = 0.4
  return cellSnapshot
 }

contextからイメージ(UIImage型のimage)を取り出すところまで実行しました。しかし、imageはディスプレイに表示する機能がありません。このimageを表示するクラスは、UIViewクラスから派生したUIImageViewなんです。

ということでイニシャライザーを使ってインスタンスを作ります。

UIImgaeView(image: image)

しかし、これをUIViewにアップキャストした「cellSnapshot」という定数にしています。

私のような初心者は、ここで「なぜ?」という疑問が生じます。そして、先に進めなくなるんです。確かに今までなら悩んで数日を費やしていたでしょう。

2年近くiOS開発の勉強をしていると、調べることなく勝手に理由を作って納得できるようになりました。その理由とは...

消費メモリーですね。UIImageViewからアップキャストして要らない情報をそぎ落として身軽(消費メモリーを節約)にできるという利点があるからでしょう。実は少し実験をしてみました。次のUIView宣言をUIImageView宣言に変更してみます。

let cellSnapshot : UIView = UIImageView(image: image)
// これを↓のように変更します。
let cellSnapshot : UIImageView = UIImageView(image: image)

return値はそのまま「cellSnapshot」をUIImageViewにしたまま返しても実行時にエラーになりません!やっぱりです。常にアップキャストは問題無いからですね。しかし、メモリー消費の観点からみれば、UIImageViewである必要はないのでUIViewにアップキャストしてやったのでしょう。

ベテランプログラマーの皆さん、私のこの考えでいいのでしょうか?

今日はここまで。