質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.69%

Swift4でlayerの再描画をしたいです

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 905

kamekame0912

score 9

swiftでMSOfficeの図形のハンドルのようなものが出来ないかと試行錯誤しております。以下のコードでハンドルとなるovalを移動するとviewに描かれている丸が拡大縮小されるようにしたいのですが、viewをremoveFromSuperlayerで消してviewを再表示しても消す前に表示されていた丸が残ってしまい、再表示するたびに丸が増えていってしまいます。viewに描画するクラスをUIViewにしたりCALayerにしたりして試したのですが丸が消えてくれません。どうにか良い方法をご教授頂けないでしょうか?

import UIKit
class ViewController: UIViewController {
    var selectLayer:CALayer!
    var touchLastPoint:CGPoint!
    var btn01:UIButton! = UIButton()
    var btn02:UIButton! = UIButton()

    var oval_w:CGFloat! = 30
    var px01:CGFloat! = 50,py01:CGFloat! = 150
    var px02:CGFloat! = 150,py02:CGFloat! = 150

    var view01:MyView! = MyView()
    var oval01:MyLayer! = MyLayer()
    var oval02:MyLayer! = MyLayer()

    override func viewDidLoad() {
        super.viewDidLoad()

        btn01.frame = CGRect(x: 50, y: 50, width: 80, height: 30)
        btn01.backgroundColor = UIColor.blue
        btn01.addTarget(self, action: #selector(btn01Tapped), for: .touchUpInside)
        self.view.addSubview(btn01)

        btn02.frame = CGRect(x: 140, y: 50, width: 80, height: 30)
        btn02.backgroundColor = UIColor.blue
        btn02.addTarget(self, action: #selector(btn02Tapped), for: .touchUpInside)
        self.view.addSubview(btn02)
    }
    @objc func btn01Tapped(){
        view01.frame = CGRect(x: 50, y: 200, width: 100, height: 100)
        view01.layer.borderColor = UIColor.black.cgColor
        view01.layer.borderWidth = 1
        view01.viewOval()
        self.view.addSubview(view01)

        oval01.frame = CGRect(x: px01, y: py01, width: oval_w, height: oval_w)
        oval01.drawOval()
        self.view.layer.addSublayer(oval01)
        oval02.frame = CGRect(x: px02, y: py02, width: oval_w, height: oval_w)
        oval02.drawOval()
        self.view.layer.addSublayer(oval02)
    }
    @objc func btn02Tapped(){
        view01.removeFromSuperview()
        oval01.removeFromSuperlayer()
    }
    func hitLayer(touch:UITouch) -> CALayer{
        var touchPoint = touch.location(in: self.view)
        touchPoint = self.view.layer.convert(touchPoint, to: self.view.layer.superlayer)
        return self.view.layer.hitTest(touchPoint)!
    }
    func selectLayerFunc(layer:CALayer?){
        if(layer == self.view.layer) || (layer == nil){
            selectLayer = nil
            return
        }
        selectLayer = layer
    }
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        selectLayer = nil
        let touch:UITouch = touches.first!
        let layer:CALayer = hitLayer(touch: touch)
        let touchPoint:CGPoint = touch.location(in: self.view)
        touchLastPoint = touchPoint
        self.selectLayerFunc(layer: layer)
    }
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        let touch:UITouch = touches.first!
        let touchPoint:CGPoint = touch.location(in: self.view)
        let touchOffsetPoint:CGPoint = CGPoint(x: touchPoint.x - touchLastPoint.x, y: touchPoint.y - touchLastPoint.y)
        touchLastPoint = touchPoint
        if(selectLayer != nil){
            let px:CGFloat = selectLayer.frame.origin.x
            let py:CGFloat = selectLayer.frame.origin.y

            CATransaction.begin()
            CATransaction.setDisableActions(true)
            selectLayer.frame.origin.x = px + touchOffsetPoint.x
            selectLayer.frame.origin.y = py + touchOffsetPoint.y
            view01.frame.size.width = oval02.frame.origin.x - oval01.frame.origin.x

            CATransaction.commit()
        }
    }
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        view01.viewOval()
    }
}

import UIKit

class MyLayer: CALayer {
    func drawOval(){
        let ovalLayer = CAShapeLayer()
        ovalLayer.strokeColor = UIColor.blue.cgColor
        ovalLayer.fillColor = UIColor.clear.cgColor
        ovalLayer.lineWidth = 1
        ovalLayer.path = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: self.frame.width, height: self.frame.height)).cgPath
        self.addSublayer(ovalLayer)
    }

}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

たぶんですが、MyLayerクラスのdrawOval関数内でself.addSublayer(ovalLayer)したovalLayerが蓄積しているだけだと思います(removeしていないので)。

drawOval()の最初で子サブレイヤーをすべて消せば期待通りにはなると思います。

MyLayerクラス自体の存在意義が無い気がするので、CAShapeLayerレイヤーをじかにview.layerに追加した方が良い気もします。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/01/09 09:56

    ありがとうござます。ご提示の方法で解決できました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.69%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる