1

I'm writing a game for tvOS that requires an object to be moved around the screen using the trackpad - rather as the mouse pointer moves around on the Mac. The problem I'm having is that, in my game, UIViewController isn't receiving touchesBegan or touchesMoved. Having read some drivel on the net about touchesBegan not working on tvOS I wrote a little program to test this theory

ViewController.h:

#import <UIKit/UIKit.h>
@interface ViewController : UIViewController {
    CGPoint cursorLocation;
    UIImageView* cursorImage;
}
@end

ViewController.m:

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    cursorImage = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, 92.0, 92.0)];
    cursorImage.center = CGPointMake(CGRectGetMidX([UIScreen mainScreen].bounds), CGRectGetMidY([UIScreen mainScreen].bounds));
    cursorImage.image = [UIImage imageNamed:@"Cursor"];

    cursorImage.backgroundColor = [UIColor clearColor];
    cursorImage.hidden = NO;
    [self.view addSubview:cursorImage];

}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    cursorLocation = CGPointMake(-1, -1);
}

- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    UITouch* touch = [touches anyObject];
    CGPoint location = [touch locationInView:self.view];
    if ((cursorLocation.x == -1) && (cursorLocation.y == -1)) {
        cursorLocation = [touch locationInView:self.view];
    } else {
        float xDiff = location.x - cursorLocation.x;
        float yDiff = location.y - cursorLocation.y;
        CGRect rect = cursorImage.frame;
        if ((rect.origin.x + xDiff >=0) && (rect.origin.x + xDiff <= self.view.frame.size.width)) {
            rect.origin.x += xDiff;
        }
        if ((rect.origin.y + yDiff >=0) && (rect.origin.y + yDiff <= self.view.frame.size.height)) { 
            rect.origin.y += yDiff;
            cursorImage.frame = rect;
            cursorLocation = location;
        }
    }
}

@end

My test worked beautifully! My question is, what could be preventing touchesBegan or touchesMoved from being received by the ViewController in my full app (the source of which is far too long for this question)? Spitball away - I'm out of ideas and I'd welcome any suggestions that you might have!

headbanger
  • 1,038
  • 1
  • 11
  • 32
  • I would suggest starting by reading the tvOS documentation on this [here](https://developer.apple.com/library/tvos/documentation/General/Conceptual/AppleTV_PG/DetectingButtonPressesandGestures.html#//apple_ref/doc/uid/TP40015241-CH16-SW1). I think you probably want pressesBegan... Also this has pretty much already been asked [here](http://stackoverflow.com/questions/32516535/how-can-i-receive-touches-using-tvos) – earthtrip Mar 24 '16 at 11:31
  • As you can see, touchesBegan works fine (as demonstrated by my test code). So the question is, why doesn't it work in the full app? And, if pressesBegan is right then why isn't there a pressesMoved as well? – headbanger Mar 24 '16 at 11:36
  • For the record, pressesBegan isn't being passed to the view controller either. Weird. – headbanger Mar 24 '16 at 14:29

2 Answers2

1

Your sample code doesn't have any gesture recognizers, but your full app probably does. Some gestures may cause touchesBegan: to never be sent to the responder chain.

You should retry your full app, but with as many gesture recognizers removed as possible, and you may find that the touchesBegan: method begins getting called.

If you determine that the problem is in fact a gesture, then you can get the gesture to cooperate with the responder chain methods by setting cancelsTouchesInView to NO on the gesture in question, or by setting delaysTouchesBegan to NO (although that should already be the default).

Justin Voss
  • 6,294
  • 6
  • 35
  • 39
  • That's an excellent suggestion. But one I've already tried. Didn't fix it. At the moment I'm suspecting that a view might be blocking the responder chain. – headbanger Mar 30 '16 at 10:06
0

The touch events will no longer be called if you enable the tvOS focus engine. Simply putting a UIButton on the screen, or for instance having a UITabBarController` will enable the focus engine and disable the touch events.

If you still need the touch events, look at this answer: UIButton blocking touchesBegan and touchesMoved

hotdogsoup.nl
  • 1,078
  • 1
  • 9
  • 22