【问题标题】:UIView subclass not receiving touchesBegan, touchesEndedUIView 子类没有接收到 touchesBegan、touchesEnded
【发布时间】:2016-01-20 15:27:27
【问题描述】:

好的,所以我有一个应用程序,它是 UIView 的子类,并且依赖于 touchesBegan 和 touchesEnded。我当然指的是这些回调:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event

前几天我将我的 iOS 从 7 更新到了 9(我知道,我很懒),发现触摸不起作用。原来上面的函数没有在我的 UIView 子类中被调用。好奇,我开始了一个空白项目,足够短,我就在这里发布代码。

main.m:

#import <UIKit/UIKit.h>
#import "AppDelegate.h"

int main(int argc, char * argv[]) {
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

这里是 AppDelegate。动态创建窗口和视图。

#import "AppDelegate.h"
#import "SubView.h"

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.

    //create a window and give it a frame. makeKeyAndVisible
    CGRect rect = [[UIScreen mainScreen] bounds];
    self.window = [[UIWindow alloc] initWithFrame:rect];
    self.window.frame = [[UIScreen mainScreen] bounds];
    [self.window makeKeyAndVisible];

    //Create a subview. Make it a red square. make sure it has a background.
    //set the userInteractionEnabled and multipleTouchEnabled and for
    //good meausure call becomeFirstResponder.
    SubView *view = [[SubView alloc] initWithFrame:CGRectMake(100,100,100,100)];
    view.backgroundColor = [UIColor redColor];
    [self.window addSubview:view];
    view.userInteractionEnabled = YES;
    view.multipleTouchEnabled = YES;
    [view becomeFirstResponder];


    //Create default UIViewControllers because Objective-C fails if the windows don't have
    //root view controllers. I don't like being muscled into MVC but what are you gonna do
    NSArray *windows = [[UIApplication sharedApplication] windows];
    for(UIWindow *window in windows) {
        if(window.rootViewController == nil){
            UIViewController* vc = [[UIViewController alloc]initWithNibName:nil bundle:nil];
            window.rootViewController = vc;
            window.userInteractionEnabled = YES;
            window.multipleTouchEnabled = YES;
        }
    }

return YES;
}

@end

这里是 SubView 类。只是有touchesBegan touchesEnded。

子视图.h

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface SubView : UIView {
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;

@end

子视图.m

#import "SubView.h"

@implementation SubView

//delegate method for touches began
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    //[super touchesBegan:touches withEvent:event];
    NSLog(@"touchesBegan!");

}


//delegate method for touches ending.
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {

    //[super touchesEnded:touches withEvent:event];
    NSLog(@"touchesEnded!");
}

//just for good measure.
- (BOOL) canBecomeFirstResponder {
    return YES;
}

@end

很简单。创建窗口,创建SubView,将SubView添加到窗口,设置userInteractionEnabled。然而,它不起作用。我看过以下 S.O.帖子:

subviews are not receiving touches

iPhone SDK - Forwarding touches from a UIViewController to a subview

touchesBegan not responding

touchesBegan in UIView not being called

touchesBegan not called in UIView subclass

touchesBegan not called in a UIView subclass

他们都说 userInteractionEnabled = YES 应该修复它,或者可能有视图覆盖另一个视图,或者视图可能有透明背景。这些都不适用这里。我设置了 view.userInteractionEnabled = YES,我什至尝试给视图提供第一响应者状态。这些似乎都没有任何好处。

精明的观察者也会看到我在窗口本身上设置了这些值:

window.userInteractionEnabled = YES;
window.multipleTouchEnabled = YES;

我试过有无。没有骰子。我试过打电话

[super touchesBegan:touches withEvent:event]

[super touchesEnded:touches withEvent:event]

在 SubView 的那些回调中。没有骰子。您能给我的任何帮助将不胜感激。谢谢!

【问题讨论】:

  • 你有没有看到 SubView?
  • 同样的问题。直接向窗口添加视图是非常狡猾的行为;添加视图然后在顶部添加视图控制器可能只是确保您的视图被遮挡。
  • 将视图添加到视图控制器而不是窗口
  • 是的,我看到 UIView 就好了。一个漂亮的红色方块。

标签: ios objective-c iphone cocoa-touch uiview


【解决方案1】:

在应用运行时查看您的视图层次结构,可以使用recursiveDescription 或使用 Xcode 7 的“调试视图层次结构”按钮。

(lldb) po [[[UIApplication sharedApplication] keyWindow] recursiveDescription]
<UIWindow: 0x7fc1f9d17b20; frame = (0 0; 414 736); gestureRecognizers = <NSArray: 0x7fc1f9d18910>; layer = <UIWindowLayer: 0x7fc1f9d16560>>
   | <SubView: 0x7fc1f9c04350; frame = (100 100; 100 100); layer = <CALayer: 0x7fc1f9c04730>>
   | <UIView: 0x7fc1f9c07500; frame = (0 0; 414 736); autoresize = W+H; layer = <CALayer: 0x7fc1f9c07fc0>>

子视图列表中后面的视图“更接近”屏幕,因此首先接收触摸。由通用UIViewController 创建的视图填满了窗口,并且位于您的SubView 前面。因此您的SubView 无法接收到触摸。

Apple 在五年前的 iOS 4.0 中将 rootViewController 属性添加到了 UIWindow。与它抗争,你只会给自己找麻烦。只需让rootViewController.view 成为您窗口中的单个顶级视图,并在其下添加您的子视图。没有人会强迫您将任何其他视图控制器添加到您的应用中。

【讨论】:

  • 完美。添加这个 [self.window.rootViewController.view addSubview:view];并删除此 [self.window addSubview:view];解决了这个问题。我不会再打架了。
猜你喜欢
  • 2013-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-03
相关资源
最近更新 更多