用於描述觸摸的窗口、位置、運動和力度。一個手指觸摸屏幕,就會生成一個 UITouch 對象,若是多個手指同時觸摸,就會生成多個 UITouch 對象。swift
(1)window:觸摸時所處的 UIWindow。 (2)view:觸摸時所處的 UIView。 (3)tapCount:短期內點按屏幕的次數。可據此判斷單擊和雙擊操做。 (4)timestamp:時間戳,單位秒。記錄了觸摸事件產生或變化時的時間。 (5)phase:觸摸事件的週期,即觸摸開始、觸摸點移動、觸摸結束和中途取消。markdown
// 返回一個CGPoint類型的值,表示觸摸在view上的位置。
// 返回的位置是針對view的座標系。
// 調用時傳入的view參數爲空的話,返回的是觸摸點在整個窗口的位置 。
open func location(in view: UIView?) -> CGPoint
// 該方法記錄了前一個座標值,返回值的含義與上面同樣。
open func previousLocation(in view: UIView?) -> CGPoint
複製代碼
一個完整的觸摸操做是一個 UIEvent,它包含一組相關的 UITouch 對象,能夠經過 UIEvent 的allTouches
屬性得到 UITouch 的集合。ide
// 手指觸碰屏幕,觸摸開始
open func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
// 手指在屏幕上移動
open func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?)
// 手指離開屏幕,觸摸結束
open func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?)
// 觸摸結束前,某個系統事件中斷了觸摸,如電話來電
open func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?)
複製代碼
當觸摸事件產生之後,App 裏有不少的 UIView 或 UIViewController,到底應該誰去響應這個事件呢?在響應以前,必需要找到那個最合適的對象(最佳響應者),這個過程稱之爲事件傳遞或尋找最佳響應者(Hit-Testing)。ui
尋找最佳響應者的原理是什麼?須要藉助如下兩個方法。spa
// 尋找最佳響應者的核心方法,傳遞事件的橋樑
// 1. 判斷點是否在當前view的內部(即調用第二個方法)
// 2. 若是在(即返回true)則遍歷其子UIView繼續
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
}
// 判斷點是否在這個View的內部
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
}
複製代碼
hitTest
方法將觸摸事件傳遞給 UIWindow,若是 UIWindow 可以響應觸摸事件,則調用其子 UIView 的hitTest
方法將事件傳遞給其子 UIView,這樣循環尋找與傳遞下去,直到獲取最佳響應者。point
方法,判斷當前觸摸位置是否在中間凸起按鈕的座標範圍內,若是在返回 true。這樣可讓觸摸事件傳遞到凸起按鈕,並讓其成爲最佳響應者。(1)不攔截,事件會沿着默認的響應鏈自動傳遞。(默認操做) (2)攔截,事件再也不往上傳遞,重寫touchesBegan
方法,但不調用父類的touchesBegan
方法。 (3)不攔截,事件繼續往上傳遞,重寫touchesBegan
方法,並調用父類的touchesBegan
方法,即super.touchesBegan(touches, with: event)
。代理
touchesBegan
方法中完成的。該方法默認是將事件順着響應者鏈向上傳遞,即將事件交給上一個響應者進行處理。每個響應者對象都有一個next
屬性,用來獲取下一個響應者。默認的next
對象爲:(1)UIView:若當前響應者是 UIViewController 的view
,則next
是 UIViewController,不然上一個響應者是其父 UIView。 (2)UIViewController:若當前響應者是 UIWindow 的rootViewController
,則next
是 UIWindow;如果被 present 顯示的則next
是presentingViewController
。 (3)UIWindow:next
爲 UIApplication。 (4)UIApplication:next
爲 AppDelegate。 (5)AppDelegate:next
爲 nil。code
class ViewController: UIViewController {
@IBOutlet var blueView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
// 建立手勢
let tap = UITapGestureRecognizer(target: self, action: #selector(gesture))
// UITapGestureRecognizer能夠設置tap次數
tap.numberOfTapsRequired = 2
let longPress = UILongPressGestureRecognizer(target: self, action: #selector(gesture))
let pinch = UIPinchGestureRecognizer(target: self, action: #selector(gesture))
let rotate = UIRotationGestureRecognizer(target: self, action: #selector(gesture))
let swipe = UISwipeGestureRecognizer(target: self, action: #selector(gesture))
// UISwipeGestureRecognizer須要設置direction
swipe.direction = .right
let pan = UIPanGestureRecognizer(target: self, action: #selector(gesture))
let edgePan = UIScreenEdgePanGestureRecognizer(target: self, action: #selector(gesture))
// UIScreenEdgePanGestureRecognizer須要設置edges
edgePan.edges = UIRectEdge.all
// 添加手勢
blueView.addGestureRecognizer(edgePan)
}
@objc func gesture(gestureRecognizer: UIGestureRecognizer) {
print(#function)
}
}
複製代碼
class ViewController: UIViewController {
@IBOutlet weak var blueView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
let gestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(gesture))
// 設置代理
gestureRecognizer.delegate = self
// 添加手勢
blueView.addGestureRecognizer(gestureRecognizer)
}
@objc func gesture(gestureRecognizer:UIGestureRecognizer){
print(#function)
}
}
extension ViewController: UIGestureRecognizerDelegate {
// 手勢識別器是否解釋這次手勢
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
if gestureRecognizer.state == .possible {
print("手勢開始")
return true
}
else if gestureRecognizer.state == .cancelled {
print("手勢結束")
return true
}
return true
}
}
複製代碼