I have a UITableView
with 3D Touch Peek and Pop enabled. I would like to be able to detect whenever the user peeks the view and whenever the user stops peeking the view without popping. I know that previewingGestureRecognizerForFailureRelationship exists. And I've tried to use it like this:
func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
// Here's where I add the gesture
let gesture = previewingContext.previewingGestureRecognizerForFailureRelationship
gesture.addObserver(self, forKeyPath: "state", options: .new, context: nil)
let sb = UIStoryboard(name: "Main", bundle: nil)
let detailVC = sb.instantiateViewController(withIdentifier: "SongPreviewViewController") as? SongPreviewViewController
return detailVC
}
and then I add
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
// can recognize peeking and canceling commit
if let object = object {
if keyPath == "state" {
let newValue = (change![NSKeyValueChangeKey.newKey]! as AnyObject).integerValue
let state = UIGestureRecognizerState(rawValue: newValue!)!
switch state {
case .possible:
print("switch - possible")
case .began:
print("switch - began")
case .changed:
print("switch - changed")
case .ended:
print("switch - ended")
case .cancelled:
print("switch - cancelled")
case .failed:
print("switch - failed")
}
}
}
}
But every time the peek view begins, .ended
is called. Does anyone have any ideas how to do this properly? Here's the reference I used for this code. Thanks for the help!
The UITapGestureRecognizer only fires when the gesture state is UIGestureRecognizerStateEnded as discussed in the following link:
About messages from UITapGestureRecognizer
All gesture recognizers begin a multi-touch sequence in the Possible state ( possible ).If you like to get at most two states: (.Possible) and (.end) you can try this code (Xcode version 9.2, swift 3.2, target 11.2) .
Change your addObserver code(Added more options) :
gesture.addObserver(self, forKeyPath: "state", options: [.prior, .old, .new], context: nil)
Get the old and new value in your observeValue method like below. It will call (.possible) and (.end) states:
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { // can recognize peeking and canceling commit if let object = object { if keyPath == "state" { var newValue:Int? guard let change = change else { return } let old = change[.oldKey] == nil || change[.oldKey] as? NSNull != nil ? "nil" : "\\(change[.oldKey]!)" let new = change[.newKey] == nil || change[.newKey] as? NSNull != nil ? "nil" : "\\(change[.newKey]!)" if change[.notificationIsPriorKey] as? Bool == true { newValue = (old as AnyObject).integerValue } else { newValue = (new as AnyObject).integerValue } let state = UIGestureRecognizerState(rawValue: newValue!)! switch state { case .possible: print("switch - possible") case .began: print("switch - began") case .changed: print("switch - changed") case .ended: print("switch - ended") case .cancelled: print("switch - cancelled") case .failed: print("switch - failed") } } }
There's another function, previewingContext(_:commit:)
which is used to tell you it will commit. You could use that to set a property, and if that isn't set you can tell the 3D Touch action didn't 'pop'. Documentation.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.