始めに
Objective-Cでviewのwidthを変えたいときなどはself.view.frame = CGRectMake(0, 0, 100, 100);
のようにframeごと書いていたのですが、Swiftを使うようになってからはview.frame.size.width = 100
と書くことが多くなってきました。
しかし、その記述方法を使用している際にハマった部分があったので、書き残しておきたいと思います。
iOS7とiOS8での違い
下記のコードは画面の中央に100x100の大きさの赤いUIViewが、ボタンをタップされることによって画面幅の正方形に拡大し、元のサイズに戻るアニメーションをするものです。
class ViewController: UIViewController {
let sampleView = UIView()
var defaultFrame = CGRectZero
override func viewDidLoad() {
super.viewDidLoad()
sampleView.backgroundColor = .redColor()
sampleView.frame.size = CGSize(width: 100, height: 100)
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
sampleView.center = view.center
defaultFrame = sampleView.frame
view.addSubview(sampleView)
}
@IBAction func insertFrameButton(sender: AnyObject) {
let width = UIScreen.mainScreen().bounds.size.width
var newFrame = CGRect(x: 0, y: 0, width: width, height: width)
newFrame.origin.y = view.center.y - width / 2
UIView.animateWithDuration(0.5, animations: {
self.sampleView.frame = newFrame
}) { finished in
UIView.animateWithDuration(0.5, animations: {
self.sampleView.frame = self.defaultFrame
}, completion: nil)
}
}
@IBAction func insertEachButton(sender: AnyObject) {
let width = UIScreen.mainScreen().bounds.size.width
UIView.animateWithDuration(0.5, animations: {
self.sampleView.frame.size.width = width
self.sampleView.frame.size.height = width
self.sampleView.center = self.view.center
}) { finished in
UIView.animateWithDuration(0.5, animations: {
self.sampleView.frame = self.defaultFrame
}, completion: nil)
}
}
}
@IBAction func insertFrameButton(sender: AnyObject)
の方では、従来通りframeに対してCGRectを代入してUIViewアニメーションさせるものです。
@IBAction func insertEachButton(sender: AnyObject)
では、width、height、centerにそれぞれ目的の値を代入してUIViewアニメーションをさせるものです。
それではそれぞれの挙動の違いを見てみましょう。
iOS8での挙動
どちらのメソッドを使っても同じアニメーションをします。
しかしiOS7ではどうでしょうか。
iOS7での挙動
@IBAction func insertEachButton(sender: AnyObject)
の場合に、想定しているアニメーションとは違う動きをしてしまいました。
最後に
UIViewのanimationのクロージャー内では、frameにCGRectを代入した方がOS間の動きの違いがないので、そちらを使ったほうが良さそうです。