【Swift/UIKit】タップした座標(位置)を取得する方法!touchesBegan

【Swift/UIKit】タップした座標(位置)を取得する方法!touchesBegan

この記事からわかること

  • Swift/UIKitタップした座標取得する方法
  • ビュー位置
  • x軸/y軸
  • touchesBeganメソッドの使用方法
  • location(in:)メソッドの使用方法
  • 長押しピンチなど他のジェスチャーの場合

index

[open]

\ アプリをリリースしました /

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

環境

iOSの座標:X軸/Y軸

iOSデバイスは以下画像のように左上を(x:0,y:0)としたX軸/Y軸として管理されており座標でビューの位置を指定することが可能になっています。

iOSデバイス画面の座標の見方とX軸Y軸の方向

Swiftでは二次元的な視覚的描画を提供する部分はCore Graphics(コアグラフィックス)で管理されているので以下の記事も参考にしてください。

タップした座標(位置)を取得する方法

UIKitでビューをタップした座標(位置)を取得するにはビュー全体のタップイベントを監視しているtouchesBeganメソッドをオーバーライドします。引数touchesからタッチイベントを参照することができるのでfirstで一番前を取り出し、location(in view:)メソッドを使用してX座標とY座標の値を取得することができます。

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
  
    // タップイベントが発生した際の処理
    if let touch = touches.first {
        let location = touch.location(in: self.view)
        print("Tapped at x:\(location.x) y:\(location.y)")
    }
}
Tapped at x:258.3333282470703 y:172.3333282470703

location(in: self.view)取得できる座標値は引数に指定したビューの(x:0,y:0)座標を基準としてそこから離れている座標値になります。そのため上記のようにself.viewに付与した場合は以下のような一番左上をタップすると(x:0,y:0)、一番右下をタップするとデバイスのサイズが取得することができます。

iOSデバイス画面の座標の見方とX軸Y軸の方向

touchesBegan(_:with:)

公式リファレンス:touchesBegan(_:with:)

func touchesBegan(
    _ touches: Set <UITouch>,
    with event: UIEvent?
)

UIResponderクラスの持つtouchesBeganメソッドはビューで1つ以上の新しいタッチが発生したことを検知するメソッドです。

location(in view:)メソッド

func location(in view: UIView?) -> CGPoint

UITouchクラスの持つlocation(in view:)メソッドは引数に指定したビュー座標におけるタップ位置を返すメソッドです。

別のビューをlocation(in view:)に指定した場合

例えばUILabelを追加して表示している場合にlocationUILabelを指定すると座標計算の基準がUILabelの一番左上(x:100,y:100)になるのでUILabelより左上をタップするとXもYも-の値になります。

class ViewController: UIViewController {
    
    private var label: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        label = UILabel(frame: CGRect(x: 100, y: 100, width: 200 , height: 100))
        label.text = "Hello World"
        label.backgroundColor = .cyan
        // UILabelはデフォルトではタッチイベントを流さないのでtrueにする
        label.isUserInteractionEnabled = true
        self.view.addSubview(label)
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        if let touch = touches.first {
            let location = touch.location(in: self.label)
            print("Tapped at x:\(location.x) y:\(location.y)")
        }
    }
}
Tapped at x:-63.333343505859375 y:-36.66667175292969

要するにlocationメソッドでは基準となるビュー(左上)を指定し、その基準点からタップされた座標がどれだけ離れているかを取得できるようになるということになります。

特定のビュー内のみでタップされた座標を検知する

touchesBeganをオーバーライドした方法ではすべてのビューでタッチイベントが発生するたびに処理が走ってしまいます。そうではなく例えばUILabel領域内をタップされた時にタップされた座標を取得したい場合UITapGestureRecognizerを使用してビュー自体にタップイベントを付与することで実装できます。

ジェスチャーイベントでは引数からUITapGestureRecognizer型を受けとることができ、ここからlocationメソッドを呼び出すことが可能です。

class ViewController: UIViewController {
    
    private var label: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        label = UILabel(frame: CGRect(x: 100, y: 100, width: 200 , height: 100))

        label.text = "Hello World"
        label.backgroundColor = .cyan
        label.isUserInteractionEnabled = true
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tapped(_:)))
        label.addGestureRecognizer(tapGesture)
        self.view.addSubview(label)
    }
    
    @objc func tapped(_ sender : UITapGestureRecognizer) {
        let location = sender.location(in: self.view)
        print("Tapped at x:\(location.x) y:\(location.y)")
    }
}

これでUILabel内をタップされた時だけ座標が表示されるようになりました。基準となる点はその時に応じて変更してください。この方法を使用することでタップ以外の長押しやピンチなど他のジェスチャーイベントが行われた際の座標も取得することができるようになります。

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

ご覧いただきありがとうございました。

searchbox

スポンサー

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑
今はCMSを使わずこのサイトを完全自作でサイト運営中〜

New Article

index