[iOS][Swift3.0] 新しくなったCGAffineTransformでUIViewの移動・拡大/縮小・回転をする

以前(〜2.x)までのSwiftでは一部APIはグローバル関数(変数)としてインポートされていました。 これらは、Swift3から記法が変更になり、それ自体の関数に置き換えられました。

Swift Evolutionでいうところの下記の内容です。

SE-0044 Import as member

今回は、一例としてCGAffineTransformのクラスを見てみます。 UIViewの移動・拡大/縮小・回転にはCGAffineTransformのtranslate,scale,rotateなどを使います。

intro

環境

今回は下記環境で試しています。

Xcode 8.2.1
Swift 3.0.2
CocoaPods 1.2.0

どう変わったのか?

上にも書いている通り、それ自体の関数に置き換えられました。例として一部関数を挙げてみます。

Swift2.xまで

// 移動
CGAffineTransformTranslate(transform, 10, 20)
// 拡大(縮小)
CGAffineTransformScale(transform, 1.2, 1.2)
// 回転
CGAffineTransformRotate(transform, 45.0)
// チェインで組み合わせ(拡大&回転)
※ 対応していない
// アフィンをつくって組み合わせる
let affine1 = CGAffineTransformMakeScale(2.0, 2.0)
let affine2 = CGAffineTransformMakeRotation(45.0)
CGAffineTransformConcat(affine1, affine2)

Swift3.0から

// 移動
transform.translatedBy(x: 10, y: 20)
// 拡大(縮小)	
transform.scaledBy(x: 1.2, y: 1.2)
// 回転
transform.rotated(by: 45.0)
// チェインで組み合わせ(拡大&回転)
transform.scaledBy(x: 1.2, y: 1.2).rotated(by: 45.0)
// アフィンをつくって組み合わせる
let affine1 = CGAffineTransform(scaleX: 2.0, y: 2.0)
let affine2 = CGAffineTransform(rotationAngle: 45.0)
affine1.concatenating(affine2)

試してみる

前提

今回、ジェスチャ認識のためにGestureRecognizerClosuresというOSSを使いました。

marcbaldwin/GestureRecognizerClosures

以下のような感じでジェスチャの動きをクロージャーで記述できます。

view.onTap { _ in
   // ここにviewがタップされた時の処理を書く
}

ライセンスはMITです。

サンプル

Storyboard上に適当に配置したViewに対してカスタムクラスを適用します。(制約は付けていません)

Main_storyboard

import UIKit
import GestureRecognizerClosures

class SampleView: UIView {

    override func awakeFromNib() {
        super.awakeFromNib()

        setupGesture()
    }

    private func setupGesture() {

        // 移動
        onPan { pan in
            let move = pan.translation(in: self)
            self.transform = self.transform.translatedBy(x: move.x, y: move.y)
            pan.setTranslation(CGPoint.zero, in: self)
        }

        // 拡大/縮小
        onPinch { pinch in
            self.transform = self.transform.scaledBy(x: pinch.scale, y: pinch.scale)
            pinch.scale = 1
        }

        // 回転
        onRotate { rotate in
            self.transform = self.transform.rotated(by: rotate.rotation)
            rotate.rotation = 0
        }
    }
}

実行結果

指で適当に操作しています。

実行サンプル

さいごに

Swift3.0以降の方が見やすく、より直感的になったのではないでしょうか。 慣れないと古い記法の方で書いてしまいそうですが、コンパイラが親切にReplaceしてくれるので影響は少ないかなと思います。