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

Swiftで遊ぼう! on Hatena

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

Swiftで遊ぼう! - 251 - draw: UIBezierPath

2016年11月16日:内容を補足*1

カスタムUIViewを用意して自分で描画する方法は、UIViewのメソッド draw() をoverride(オーバーライド)させるのが一般的です*2。しかし、カスタムUIViewを作る場合、ちゃんとイニシャライザを使う方法を理解する必要もあるので、Swiftで遊ぼう! - 248 - UIViewの初期化ステップ - Swiftで遊ぼう! on Hatenaをちゃんと理解しましょう。

draw() の使用法

2つの方法があります。

C言語仕様(OOPでは無い)のAPIでCore Graphicsを使う方法*3OOP指向のUIBezierPathを使う方法です。

Core Graphics

UIGraphicsGetCurrentContext()メソッドを使って、contextをdrawに使用します。
pathを作ります。
pathの属性を設定します。
pathを閉じます。

UIBezierPath

基本的に上述と同じですが、すべてUIBezierPathインスタンス内で処理されます。
1. contextも自動的に作られます。
2. pathを作って属性を変更できます。
3. UIColor(タイプメソッド)*4を使って色をつけます。
4. pathをfillしてstrokeすれば描画です。

どちらかと言えばUIBezierPathクラスを使う方法が一般的です。

三角形の描画を考えてみます。まず適当にSinble View Applicationプロジェクトを作ります。テンプレートで用意されているViewControllerにViewというスーパービューが用意されていますが、オブジェクト・ライブラリから新しくジェネリックナViewをドラッグ&ドロップしてスーパービューに重ねます*5

次にメニューからFile > New > File...を選んで、Cocoa Touch Classを選んで、UIViewをサブクラスにした「TestView」を作ります*6

class TestView: UIView {

    /*
    // Only override draw() if you perform custom drawing.
    // An empty implementation adversely affects performance 
    // during animation.
    override func draw(_ rect: CGRect) {
        // Drawing code
    }
    */

}

空っぽのファイルができています。ここに描画をするのに重要なメソッドが「draw」なんで、コメントアウトしたdrawを有効にする*7必要があります。draw()メソッド内に次のコードを加えていきます。

まずUIBezierPathはクラスなのでオブジェクト生成(インスタンス)させます。

        let path = UIBezierPath()

カスタムUIViewに空のBezierPathインスタンスが生成させます。

次に空のインスタンスに属性を与えます。

        path.move(to: CGPoint(x:160, y:50))
        // カスタムビュー上の座標(160, 50)に移動
        path.addLine(to: CGPoint(x:220, y:150))
        // (160, 50)から(220, 150)に線が引かれます
        path.addLine(to: CGPoint(x: 90, y: 150))
        // 次に(220, 150)から(90, 150)に線ができます
        path.close()
        // (90, 150)から(160, 50)へ最短距離(直線)で閉じます

これでpathの位置が決められたので色や線の太さを設定します。

        UIColor.green.setFill()
        UIColor.red.setStroke()
        path.lineWidth = 3.0

最後は描画ステップです。

        path.fill() // ここで初めて内部の色が出現
        path.stroke() // これでアウトラインが描画される

なるほどです。iPhone SEシュミレーターで実行すると上手くいきました!
f:id:yataiblue:20160926160948j:plain

*1:2016年9月19日:Xcode 8 & Swift 3向けに改訂、2016年5月16日:少し調整

*2:注意:draw() をユーザーが「Call」してはいけません!必ずシステムに任せなければ描画がおかしくなります。

*3:もしかして、CGFloat、CGPointやCGSizeの頭についている「CG」ってこれのことでしょうか?

*4:Colors」、「Fonts」、「Texts」、「Images」以外の属性はすべてUIBezierPathが持っています。この4つだけはタイプメソッドを使ってオブジェクト全体に効果を反映させるので、利用時に少し違和感を感じますが、これは慣れるしかないでしょう。

*5:コンストレイントは必ず設定します。

*6:ストーリーボード上でジェネリックナViewを選択してアトリビュート・インスペクタにある「Class」から「TestView」を選択しないと描画されないので注意!

*7:Swiftで遊ぼう! - 471 - Xcode 8 用語説明とショートカット - Swiftで遊ぼう! on Hatenaで説明している「Ctrl + /」を使います。