繁体   English   中英

为什么我的UIViewController不在响应链中来查看它?

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

我编写了一个UIViewController的子类,它以编程方式创建一个视图,而不是从NIB文件加载它。

它有一个简单的loadView方法:

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

...然后我在viewDidLoad进行大量初始化,如文档所述。 一切正常,我可以看到包含自定义视图的滚动视图。

我需要一个UIViewController来拥有视图,因为它是UINavigationBar工作流的一部分。 由于我有一个控制器对象,我宁愿它做控制器的东西。

那么问题是我的视图控制器似乎不在响应链中。 touchesBegan:withEvent:如果我在根视图或子视图中定义它,则会被调用,但如果它在视图控制器本身中则不会被调用。

Apple事件处理文档明确提到视图控制器应该在响应者链中 UIViewController文档没有说明除了将根视图分配给self.view属性之外所需的额外步骤,正如我上面所做的那样。 UIResponder文档声称UIView应该弄清楚它是否有控制器并将事件传递给它。 UIScrollView文档什么都没说。

我还尝试了userInteractionEnabled:各种设置userInteractionEnabled:对于所有视图和子视图,没有运气。

我错过了什么?

EricB,只有在没有处理的情况下才会向响应者链发送触摸。 UIScrollView显然处理所有触摸事件,因此它不向它发送任何东西的nextResponder。 对我来说很有意义。

你真正想要的是在UIScrollView的滚动逻辑处理之前“过滤”触摸事件。 但请注意,响应者链是这项工作的错误工具,正是因为它不允许在处理之前拦截事件。

在您的情况下,最好的解决方案可能是子类UIScrollView,覆盖触摸方法(touchesBegan等)并在调用[super touchesXxx]之前手动将事件发送给委托。

我认为问题是UIScrollView有很多错误,并且有bug的变通方法,以及bug的变通方法中的错误:)。

事实上,从长远来看,子类化UIScrollView通常是一个坏主意这一事实很复杂 - 你经常不得不将其子类化为其他任何无法解决的原因,所以如果你想重新使用你的代码,请尝试不要将它子类化,直到你绝对必须。

最简单的解决方案我发现一致的工作是让你的内容视图成为一个小的UIView子类 - 请记住你的内容视图本身是UIScrollView必须永远不会改变的(例如,如果你启用缩放 - Apple至少有一些错误到iOS 6当您更改现有滚动视图的内容视图时启动,因此最好保持简单,并将自定义视图作为子视图放在其中。

注意:在多个已发布的应用程序中,这一直对我有用。 如果有问题,我还没有看到它。 我不知道为什么Apple自己不实现这个简单的改变,除非它有一个微妙的问题,我还没有遇到过!

用法:

/** 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;
}

接口文件+类文件:

#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

UIScrollView默认会延迟内容触摸; 你看过-delaysContentTouches,以确保触摸将通过。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM