views:

966

answers:

2

I have written a subclass of UIViewController which creates a view programmatically, instead of loading it from a NIB file.

It has a simple loadView method:

- (void)loadView
{
    UIScrollView *mainScrollView =
        [[UIScrollView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.view = mainScrollView;
    [mainScrollView release];
}

...then I do the bulk of my initialization in viewDidLoad, as documented. It all works, and I can see the scroll view with my custom views in it.

I need a UIViewController to own the view because it's part of a UINavigationBar workflow. Since I have a controller object, I'd rather it do the controller stuff.

The problem, then, is my view controller does not seem to be in the responder chain. touchesBegan:withEvent: is invoked if I define it in the root view or a subview, but not if it's in the view controller itself.

Apple event handling documentation glibly mentions the view controller should be in the responder chain. UIViewController documentation says nothing about extra steps needed beyond assigning the root view to the self.view property, as I've done above. UIResponder documentation claims a UIView should figure out if it has a controller and pass the event to it. UIScrollView documentation says nothing at all.

I've also experimented with various settings of userInteractionEnabled: for all views and subviews, with no luck.

What am I missing?

A: 

UIScrollView will delay content touches by default; have you looked at -delaysContentTouches to make sure the touches will pass through.

Ben Stiglitz
They pass through just fine to other views on the responder chain, just not the view controller.
EricB
+1  A: 

EricB, touches are sent down the responder chain only if they have not been handled. UIScrollView obviously handles all the touch events, so it does not send anything to it's nextResponder. Makes perfect sense to me.

What you actually want is to “filter” touch events before they are handled by the scrolling logic of UIScrollView. But note that the responder chain is a wrong tool for this job, exactly because it does not allow to intercept the events before they get handled.

Probably the best solution in your case is to subclass UIScrollView, override the touch methods (touchesBegan etc) and manually send the events to the delegate before calling [super touchesXxx].

Andrey Tarantsov