Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to detect all touches in Swift 2

I'm trying to create a timeout function for an app I'm develop using Swift 2 but in swift 2, you can put this code in the app delegate and it works but it does not detect any keyboard presses, button presses, textfield presses, and etc:

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    super.touchesBegan(touches, withEvent: event);
    let allTouches = event!.allTouches();

    if(allTouches?.count > 0) {
        let phase = (allTouches!.first as UITouch!).phase;
        if(phase == UITouchPhase.Began || phase == UITouchPhase.Ended) {
            //Stuff
            timeoutModel.actionPerformed();
        }
    }
}

Before swift 2, I was able to have the AppDelegate subclass UIApplication and override sendEvent: like this:

-(void)sendEvent:(UIEvent *)event
{
    [super sendEvent:event];

    // Only want to reset the timer on a Began touch or an Ended touch, to reduce the number of timer resets.
    NSSet *allTouches = [event allTouches];
    if ([allTouches count] > 0) {
        // allTouches count only ever seems to be 1, so anyObject works here.
        UITouchPhase phase = ((UITouch *)[allTouches anyObject]).phase;
        if (phase == UITouchPhaseBegan || phase == UITouchPhaseEnded)
            [[InactivityModel instance] actionPerformed];
    }
}

The code above works for every touch but the swift equivalent only works when a view does not exist above that UIWindow's hierarchy?

Does anyone know a way to detect every touch in the application?

like image 624
FireDragonMule Avatar asked Jul 26 '15 23:07

FireDragonMule


People also ask

How do you use touch gestures in Swift?

Screen edge pan - A fingertip slides in a dragging motion that starts near the edge of the screen. Long press - A fingertip touches and presses down on the screen. You can create touch gestures on an app’s user interface solely through Swift code or by placing gesture recognizer objects on a view from the Object Library.

How do I detect Tap gestures in Xcode?

By default, a tap gesture recognizes a single tap by one fingertip, but you can define multiple taps by two or more fingertips. To see how to detect tap gestures, follow these steps: Click the Main.storyboard file in the Navigator pane. Xcode displays the single view.

How do I use the long press gesture recognizer in Swift?

Move the mouse pointer over the Long Press Gesture Recognizer icon in the Document Outline or at the top of the View Controller, hold down the Control key, and Ctrl-drag from the Long Press Gesture Recognizer above the last curly bracket in the ViewController.swift file. Release the Control key and the left mouse button.

How do I detect up and down swipes?

Each swipe gesture recognizer can only detect swipes in a single direction. That means if you want to detect an up and down swipe, you’ll need to define two separate swipe gesture recognizers where one recognizes only up swipes and the second only recognizes down swipes.


1 Answers

As I have something similar in my application, I just tried to fix it:

  • override sendEvent in UIWindow - doesn't work
  • override sendEvent in delegate - doesn't work

So the only way is to provide custom UIApplication subclass. My code so far (works on iOS 9) is:

@objc(MyApplication) class MyApplication: UIApplication {

  override func sendEvent(event: UIEvent) {
    //
    // Ignore .Motion and .RemoteControl event
    // simply everything else then .Touches
    //
    if event.type != .Touches {
      super.sendEvent(event)
      return
    }

    //
    // .Touches only
    //
    var restartTimer = true

    if let touches = event.allTouches() {
      //
      // At least one touch in progress?
      // Do not restart auto lock timer, just invalidate it
      //
      for touch in touches.enumerate() {
        if touch.element.phase != .Cancelled && touch.element.phase != .Ended {
          restartTimer = false
          break
        }
      }
    }

    if restartTimer {
      // Touches ended || cancelled, restart auto lock timer
      print("Restart auto lock timer")
    } else {
      // Touch in progress - !ended, !cancelled, just invalidate it
      print("Invalidate auto lock timer")
    }

    super.sendEvent(event)
  }

}

Why there's @objc(MyApplication). That's because Swift mangles names in a different way then Objective-C and it just says - my class name in Objective-C is MyApplication.

To make it working, open your info.plist and add row with Principal class key and MyApplication value (MyApplication is what's inside @objc(...), not your Swift class name). Raw key is NSPrincipalClass.

enter image description here

like image 56
zrzka Avatar answered Oct 01 '22 03:10

zrzka