Touches began in UITableViewController
Asked Answered
P

5

9

I am defining this method in my UITableViewController subclass:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    [super touchesBegan:touches withEvent:event];
    NSLog(@"touch began");
}

but it's not being triggered. UIViewController is a subclass of UIResponder so it should work, right? Thanks

Pacifica answered 8/6, 2011 at 22:53 Comment(0)
L
4

Yep, that should definitely work.

Make sure User Interaction Enabled is set for the view this controller corresponds to.

If the view is loaded from a nib/xib, make sure File's Owner is set to be the appropriate class name, and File's Owner's view outlet is connected to proper the view.

Update: I see this behavior as well, using an app built with the Nav-based App template, but with a View-based App template, it works as expected.

I think that in the case of a Navigation Controller, the table view embedded in the view controller is getting the event before the view controller does. See the UIView reference (emphasis mine):

View controllers are themselves descendants of the UIResponder class and are inserted into the responder chain between the managed root view and its superview, which typically belongs to a different view controller. If the view controller’s view does not handle an event, the view controller itself has the option of handling the event before passing the event along to the superview.

This implies that the view has the first chance to handle the event, and if it does, the view controller won't get it.

Not exactly clear what you're trying to accomplish, so I'm not sure what solution to offer.

Lastditch answered 9/6, 2011 at 0:23 Comment(3)
Hey, thanks for your reply. I made a fresh XCode navigation project and added the touchesbegan method in UITableViewController subclass (didn't change anything else), but it doesn't workPacifica
Thanks for your detailed answer. Basically, I have a UITextField of type UIKeyboardTypeNumber pad, and I want to resign first responder (dismiss keyboard) whenever user clicks anywhere on the screen.Pacifica
@Lastditch I am trying to show something on the screen as soon as the user puts their finger down on the table view and hide it when they lift their finger. Seeing as the events don't all bubble up from the table view as you described, how can I accomplish what I am trying to do?Doolie
S
5

If you are trying to dismiss a keyboard in a UITableViewController, a decent solution is to call resignFirstResponder in the tableView delegate's didSelectRowAtIndexPath method.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [myTextField resignFirstResponder];

    // Rest of your actual didSelectRowAtIndexPath code ...
}
Sackcloth answered 12/5, 2012 at 21:4 Comment(1)
Hey I had a similar problem. From the comments above in the accepted answer, its clear that the @Pacifica didnt get his problem solved, but its still accepted ! But your solution works for me !!!Philosophy
L
4

Yep, that should definitely work.

Make sure User Interaction Enabled is set for the view this controller corresponds to.

If the view is loaded from a nib/xib, make sure File's Owner is set to be the appropriate class name, and File's Owner's view outlet is connected to proper the view.

Update: I see this behavior as well, using an app built with the Nav-based App template, but with a View-based App template, it works as expected.

I think that in the case of a Navigation Controller, the table view embedded in the view controller is getting the event before the view controller does. See the UIView reference (emphasis mine):

View controllers are themselves descendants of the UIResponder class and are inserted into the responder chain between the managed root view and its superview, which typically belongs to a different view controller. If the view controller’s view does not handle an event, the view controller itself has the option of handling the event before passing the event along to the superview.

This implies that the view has the first chance to handle the event, and if it does, the view controller won't get it.

Not exactly clear what you're trying to accomplish, so I'm not sure what solution to offer.

Lastditch answered 9/6, 2011 at 0:23 Comment(3)
Hey, thanks for your reply. I made a fresh XCode navigation project and added the touchesbegan method in UITableViewController subclass (didn't change anything else), but it doesn't workPacifica
Thanks for your detailed answer. Basically, I have a UITextField of type UIKeyboardTypeNumber pad, and I want to resign first responder (dismiss keyboard) whenever user clicks anywhere on the screen.Pacifica
@Lastditch I am trying to show something on the screen as soon as the user puts their finger down on the table view and hide it when they lift their finger. Seeing as the events don't all bubble up from the table view as you described, how can I accomplish what I am trying to do?Doolie
S
3

I just ran into the exact issue as the original posting. I got around the issue by creating a subclass of UITableView and overriding the "touchesBegan" method. I also created a protocol so the UITableView could call a method on the UITableViewController, which is ultimately where I wanted to handle the "touchesBegan" event.

Here is the header for UITableView subtype:

@protocol AGSTableViewDelegate;

@interface AGSTableView : UITableView
@property (nonatomic, weak) id<AGSTableViewDelegate> agsDelegate;
@end

@protocol AGSTableViewDelegate<NSObject>
-(void)tableViewTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
@end

And implementation:

@implementation AGSTableView

@synthesize agsDelegate;

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{    
    [super touchesBegan:touches withEvent:event];

    if (agsDelegate)
        [agsDelegate tableViewTouchesBegan:touches withEvent:event];
}
@end

And finally, the code fragments from UITableViewController:

@interface AGSWasteUpdateTableController ()<AGSTableViewDelegate>
@end

- (void)viewDidLoad
{
    AGSTableView *tableView = (AGSTableView *)[self tableView];
    tableView.agsDelegate = self;
}

-(void)tableViewTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [yourTextField resignFirstResponder];
}

Hope this helps...

Sachi answered 11/4, 2012 at 20:26 Comment(0)
P
2

Swift Version because I just had this very issue:

import UIKit

class BubbleTouchesTableView: UITableView {

    // Designed to bubble up touches from a UITableView

    override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
        super.touchesBegan(touches, withEvent: event)
        self.nextResponder()?.touchesBegan(touches, withEvent: event)
    }

    override func touchesCancelled(touches: NSSet, withEvent event: UIEvent) {
        super.touchesCancelled(touches, withEvent: event)
        self.nextResponder()?.touchesCancelled(touches, withEvent: event)
    }

    override func touchesEnded(touches: NSSet, withEvent event: UIEvent) {
        super.touchesEnded(touches, withEvent: event)
        self.nextResponder()?.touchesEnded(touches, withEvent: event)
    }

    override func touchesMoved(touches: NSSet, withEvent event: UIEvent) {
        super.touchesMoved(touches, withEvent: event)
        self.nextResponder()?.touchesMoved(touches, withEvent: event)
    }

}
Plasia answered 15/3, 2015 at 23:7 Comment(0)
P
1

You need to pass the touches up the responder chain. We can do this by subclassing UITableView and overriding touchesBegan (and others if needed) and then passing the touches up the responder chain to the UITableViewController.

UITableViewTouch.h:

#import <UIKit/UIKit.h>

@interface UITableViewTouch : UITableView

@end

UITableViewTouch.m:

#import "UITableViewTouch.h"

@implementation UITableViewTouch

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    [super touchesBegan:touches withEvent:event];
    [[self nextResponder] touchesBegan:touches withEvent:event];
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
    [super touchesCancelled:touches withEvent:event];
    [[self nextResponder] touchesCancelled:touches withEvent:event];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    [super touchesEnded:touches withEvent:event];
    [[self nextResponder] touchesEnded:touches withEvent:event];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    [super touchesMoved:touches withEvent:event];
    [[self nextResponder] touchesMoved:touches withEvent:event];
}

@end
Pigsty answered 28/12, 2012 at 23:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.