現在のViewの作りですと、仮に touchView.isUserInteractionEnabled
をfalse
にしても、touchesMoved()が呼ばれ続けてしまうため、Viewのドラッグは止まらないかと思います。
下記のサンプルコードでは次のような対応をおこないました。
- ViewのtouchesBegan()でドラッグされているかどうかのフラグを追加しました
- フラグが立っていなければ Viewが動かないようにしました
- hoge() が実行されたら touchesEnded() を呼ぶようにしました
- それ以降はフラグが落ちるので Viewが動かなくなります
import UIKit
final class View: UIView {
var touched: Bool = false
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
touched = true
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
guard touched else { return }
guard let touch = touches.first else { return }
let location = touch.location(in: self)
let previousLocation = touch.previousLocation(in: self)
let draggedDistanceX = location.x - previousLocation.x
let draggedDistanceY = location.y - previousLocation.y
var newFrame = frame
newFrame.origin.x += draggedDistanceX
newFrame.origin.y += draggedDistanceY
frame = newFrame
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesCancelled(touches, with: event)
touched = false
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesEnded(touches, with: event)
touched = false
}
}
class ViewController: UIViewController {
@IBOutlet weak var touchView: View!
@IBOutlet weak var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
// 5秒後にタッチをドラッグを強制的にキャンセルする
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(5)) { [weak self] in
self?.hoge()
}
}
private func hoge() {
label.text = "called hoge."
resignFirstResponder()
touchView.touchesEnded([UITouch()], with: UIEvent())
}
}
上記のサンプルコードを実行した動画を添付します。5秒のタイマーが満了するとhoge()
を実行してタッチ対象から外すようにしました。
にて検証をおこないました。GitHubに検証に使ったプロジェクトをアップロードいたしました。参考になれば幸いです。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。