简体   繁体   中英

Detect when 3D Touch Peek and Pop View is Canceled

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) .

  1. Change your addObserver code(Added more options) :

     gesture.addObserver(self, forKeyPath: "state", options: [.prior, .old, .new], context: nil)
  2. 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM