Why isn't my UIViewController in the responder chain for its view?

前端 未结 3 924
迷失自我
迷失自我 2020-12-17 06:55

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 met

相关标签:
3条回答
  • 2020-12-17 06:58

    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].

    0 讨论(0)
  • 2020-12-17 07:12

    I think the problem is that UIScrollView has a lot of bugs, and workarounds to the bugs, and bugs in the workarounds to the bugs :).

    It's complicated by the fact that subclassing UIScrollView is usually a bad idea in the long run - you'll often have to subclass it for other reasons that cannot be solved any other way, so if you want to re-use your code, try not to subclass it until you absolutely have to.

    Simplest solution I've found that works consistently is to make your content view a tiny UIView subclass - bearing in mind your content view itself is REQUIRED by UIScrollView to never change (e.g. if you enable zooming - Apple has some bugs up to at least iOS 6 that kick in when you change the content view of an existing scrollview), so it's a good idea to keep it trivial, and put your custom views inside it as subviews.

    NB: This has always worked for me, on multiple shipped apps. If there's a problem, I haven't seen it yet. I have no idea why Apple doesn't implement this simple change themselves, unless there's a subtle problem with it that I haven't run into yet!

    Usage:

    /** Inside your UIViewController, wherever you set the root content view
    of your UIScrollView, you have to also tell the custom class "I am the nextResponder!"
    */
    -(void)viewDidLoad
    {
        self.scrollView.contentSize = self.viewEmbeddedInScrollview.frame.size;
        self.viewEmbeddedInScrollview.nextResponderHeyAppleWhyDidYouStealThis = self;
    }
    

    Interface file + class file:

    #import <UIKit/UIKit.h>
    
    @interface UIViewThatNeverLosesItsNextResponder : UIView
    
    @property(nonatomic,retain) UIResponder* nextResponderHeyAppleWhyDidYouStealThis;
    
    @end
    
    
    
    #import "UIViewThatNeverLosesItsNextResponder.h"
    
    @implementation UIViewThatNeverLosesItsNextResponder
    
    - (id)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {
            // Initialization code
        }
        return self;
    }
    
    @synthesize nextResponderHeyAppleWhyDidYouStealThis;
    
    -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    {
        [nextResponderHeyAppleWhyDidYouStealThis touchesBegan:touches withEvent:event];
    }
    
    -(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
    {
        [nextResponderHeyAppleWhyDidYouStealThis touchesCancelled:touches withEvent:event];
    }
    
    -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
    {
        [nextResponderHeyAppleWhyDidYouStealThis touchesEnded:touches withEvent:event];
    }
    
    -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
    {
        [nextResponderHeyAppleWhyDidYouStealThis touchesMoved:touches withEvent:event];
    }
    
    @end
    
    0 讨论(0)
  • 2020-12-17 07:22

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

    0 讨论(0)
提交回复
热议问题