2016-04-20 7 views
0

Ich habe 2 GesturerRecognizers, eine ist eine benutzerdefinierte 3DTouch und eine andere ist die einzelne UITapGestureRegognizer. Ich würde gerne machen, dass wenn du einmal tippst, es einen Übergang durchführt und wenn du den 3dtouch betrachtest, bekommst du eine andere Ansicht. Ich habe viele Dinge ausprobiert, aber es funktioniert nicht (i auch mit Timer versucht, aber immer 0 beim Start, keine Fragen, wenn sein 3DTouch oder nicht.) Das ist meine 3DTouch benutzerdefinierte Implementierung:Diference zwischen 2 GestureRecognizer

//Without this import line, you'll get compiler errors when implementing your touch methods since they aren't part of the UIGestureRecognizer superclass 
import UIKit.UIGestureRecognizerSubclass 

//Since 3D Touch isn't available before iOS 9, we can use the availability APIs to ensure no one uses this class for earlier versions of the OS. 
@available(iOS 9.0, *) 
public class ForceTouchGestureRecognizer: UIGestureRecognizer { 

    var timer = NSTimer() 
    var counter = Double() 

    //Since it also doesn't make sense to have our force variable as a settable property, I'm using a private instance variable to make our public force property read-only 
    private var _force: CGFloat = 0.0 

    //Because we don't know what the maximum force will always be for a UITouch, the force property here will be normalized to a value between 0.0 and 1.0. 
    public var force: CGFloat { get { return _force } } 
    public var maximumForce: CGFloat = 4.0 

    func timerAction() { 
     counter += 1 
    } 


    override public func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent) { 
     super.touchesBegan(touches, withEvent: event) 
     counter = 0 

     timer = NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: #selector(timerAction), userInfo: nil, repeats: true) 
     print("COUNTER: \(counter)") 

     normalizeForceAndFireEvent(.Began, touches: touches) 
    } 

    override public func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent) { 
     super.touchesMoved(touches, withEvent: event) 

     normalizeForceAndFireEvent(.Changed, touches: touches) 
    } 

    override public func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent) { 
     super.touchesEnded(touches, withEvent: event) 
     print("COUNTER: \(counter)") 

     normalizeForceAndFireEvent(.Ended, touches: touches) 
     timer.invalidate() 

    } 

    override public func touchesCancelled(touches: Set<UITouch>, withEvent event: UIEvent) { 
     super.touchesCancelled(touches, withEvent: event) 

     normalizeForceAndFireEvent(.Cancelled, touches: touches) 
    } 

    func normalizeForceAndFireEvent(state: UIGestureRecognizerState, touches: Set<UITouch>) { 
     //Putting a guard statement here to make sure we don't fire off our target's selector event if a touch doesn't exist to begin with. 
     guard let firstTouch = touches.first else { 
      return 
     } 

     //Just in case the developer set a maximumForce that is higher than the touch's maximumPossibleForce, I'm setting the maximumForce to the lower of the two values. 
     maximumForce = min(firstTouch.maximumPossibleForce, maximumForce) 

     //Now that I have a proper maximumForce, I'm going to use that and normalize it so the developer can use a value between 0.0 and 1.0. 
     _force = firstTouch.force/maximumForce 

     //Our properties are now ready for inspection by the developer. By setting the UIGestureRecognizer's state property, the system will automatically send the target the selector message that this recognizer was initialized with. 
     self.state = state 
    } 

    //This function is called automatically by UIGestureRecognizer when our state is set to .Ended. We want to use this function to reset our internal state. 
    public override func reset() { 
     super.reset() 

     _force = 0.0 
    } 
} 

Und das in der Ansicht ist, was ich tun:

 self.forceTouchRecognizer = ForceTouchGestureRecognizer(target: self, action: #selector(PLView.handleForceTouchGesture(_:))) 
    self.addGestureRecognizer(forceTouchRecognizer) 

    self.nowTap = UITapGestureRecognizer(target: self, action: #selector(StoryTableViewController.didTapRightNow2(_:))) 
    self.addGestureRecognizer(nowTap) 

Antwort

2

Wenn ich Sie richtig verstehe Sie 2 verschiedene GestureRecognizers zum gleichen UIView hinzufügen möchten. Einer, der einen normalen Wasserhahn erkennt und einen, der einen Wasserhahn mit Gewalt erkennt.

Für das normale Tippen können Sie einen UITapGestureRecognizer verwenden. Für den Kraftabgriff müssen Sie einen eigenen benutzerdefinierten Gestenerkenner erstellen, der die Kraft der Berührung überwacht, um zu entscheiden, ob die Kraft hoch genug war, um sich für eine Kraftangriffsgeste zu qualifizieren. Hier

ist die individuelle Kraft tap Gestenerkenner:

import UIKit.UIGestureRecognizerSubclass 

@available(iOS 9.0, *) 
public class ForceTapGestureRecognizer: UIGestureRecognizer { 

    private var forceTapRecognized = false 

    override public func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent) { 
     super.touchesBegan(touches, withEvent: event) 
     forceTapRecognized = false 
    } 

    override public func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent) { 
     super.touchesMoved(touches, withEvent: event) 
     guard let touch = touches.first else { return } 
     if touch.force >= touch.maximumPossibleForce { 
      forceTapRecognized = true 
     } 
    } 

    override public func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent) { 
     super.touchesEnded(touches, withEvent: event) 
     state = forceTapRecognized ? .Ended : .Failed 
    } 
} 

Dann können Sie beide Erkenner zu Ihrer Ansicht hinzuzufügen und eine Aktion für jede Erkennungs hinzuzufügen.

Um beide Erkenner machen zur gleichen Zeit arbeiten Sie die UITapGestureRecognizer zu sagen haben, dass es nur einen Hahn erkennen soll, wenn die ForceTapGestureRecognizer keine Kraft Hahn erkannt hat. Sie tun dies mit requireGestureRecognizerToFail(_:). Wenn Sie dies nicht einstellen, werden nur die normalen Taps erkannt:

class ViewController: UIViewController { 

    let touchView = UIView(frame: CGRect(x: 100, y: 100, width: 100, height: 100)) 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     let touchView = UIView() 
     view.addSubview(touchView) 

     let forceTapRecognizer = ForceTapGestureRecognizer(target: self, action: #selector(ViewController.didForceTap(_:))) 
     let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(ViewController.didTap(_:))) 
     tapRecognizer.requireGestureRecognizerToFail(forceTapRecognizer) 
     touchView.addGestureRecognizer(forceTapRecognizer) 
     touchView.addGestureRecognizer(tapRecognizer) 
    } 

    func didTap(recognizer: UITapGestureRecognizer) { 
     print("tap") 
    } 

    func didForceTap(recognizer: ForceTapGestureRecognizer) { 
     print("force tap") 
    } 
}