子类化 UIApplication 以覆盖 sendEvent 导致崩溃

Posted

技术标签:

【中文标题】子类化 UIApplication 以覆盖 sendEvent 导致崩溃【英文标题】:Subclassing UIApplication to override sendEvent causes crash 【发布时间】:2011-05-02 01:57:23 【问题描述】:

我正在尝试子类 UIApplication 来捕获所有触摸事件,这用于查看用户是否是 afk 。无论如何,它在您第一次启动应用程序时效果很好。如果你把它放在后台并再次打开它2次,它就会崩溃。我不知道是什么原因造成的。我在 [super sendEvent:event] 上收到 EXEC_BAD_ACCESS;

我的子类 MyUI:

@implementation MyUI

- (void)sendEvent:(UIEvent *)event 
    [super sendEvent:event]; // <-- EXEC_BAD_ACCESS

    if (event.type == UIEventTypeTouches) 
        UITouch *touch = [event allTouches].anyObject;
        if (touch.phase == UITouchPhaseBegan) 
           // Calling some methods
        
     
  
@end

Main.m

int main(int argc, char *argv[])

    NSString* appClass = @"MyUI";
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    int retVal = UIApplicationMain(argc, argv, appClass, nil);
    [pool release];
    return retVal;

【问题讨论】:

可以添加堆栈跟踪吗?我在我的应用程序中使用相同的方法来跟踪每个触摸事件,并且效果很好。 【参考方案1】:

首先调用超类方法是否有原因?如果你正在拦截,你应该最后调用它。

这可能是你的问题。我还重写了 sendEvent 以拦截到我的应用程序的所有事件并且没有问题。

如果您首先调用超级方法,它会将其传递给最终可能会吃掉您的事件的所有 UIResponder,从而导致 EXEC_BAD_ACCESS。此外,正如 DavidNeiss 建议的那样,消除超级呼叫下方的线条。如果您仍然收到错误的访问信号,则可能是另一个视图或控制器导致它。您需要堆栈跟踪以找出它在哪里。

【讨论】:

【参考方案2】:

要获得 EXEC_BAD_ACCESS 的确切原因,请在您的应用程序中使用 nszombieenabled。 此链接将指导您使用它。 http://iosdevelopertips.com/debugging/tracking-down-exc_bad_access-errors-with-nszombieenabled.html

【讨论】:

你能解释一下你在哪里泄漏了吗?我有同样的问题 完全正确;如果此答案帮助您找到问题,请更新您的问题或添加评论,解释原因是什么/您如何解决它。它可能会帮助其他人!【参考方案3】:

不明白“afk”是什么意思。

另一种方法可能是创建自定义手势识别器。它们(手势识别器)应该在作为正常触摸事件处理的一部分转发到视图之前过滤触摸事件。

【讨论】:

afk 表示远离键盘。换句话说,我正在检查用户是否仍在使用 ipad/iphone 或者用户是否离开。 好的,UIApplication 类将事件转发到 UIWindow。如果不是子类化 UIApplication,而是子类化 UIWindow 并将处理坚持在它的 - (void)sendEvent:(UIEvent *)event 方法中。我已经尝试过了,并添加了一个 NSLog()/[super sendEvent:event] 到我的并看到事件发生了。 另外,就你的做法而言,如果你只有“ [super sendEvent:event]; // 【参考方案4】:

为了简单起见,我会将@"MyUI" 直接放入 UIApplicationMain 调用中。

字符串很可能是您的问题。它在NSAutoreleasePool 之外,还没有完成。

另外,@"MyUI" 这个名字暗示了一个视图控制器,而不是一个 AppDelegate 类。调查一下。

【讨论】:

【参考方案5】:

[超级发送事件:事件]; //

表示你的班级有错误。

用于测试块

/*
- (void)sendEvent:(UIEvent *)event 
    [super sendEvent:event]; // <-- EXEC_BAD_ACCESS

    if (event.type == UIEventTypeTouches) 
        UITouch *touch = [event allTouches].anyObject;
        if (touch.phase == UITouchPhaseBegan) 
           // Calling some methods
        
     
 
*/

你仍然会得到那个错误。任何时候如果您在覆盖 sendEvent 时遇到错误 尝试阻止所有覆盖方法并检查您是否仍然收到该错误,或​​者不是专门针对此行[super sendEvent:event];。我也遇到了这个错误,并且发现这种方法没有错误。在applicationDidFinishLaunching 中发现了错误。始终将代码保留在 try catch 方法中

@try 


@catch (NSException *exception) 
    NSLog(@"Exception => %@",exception);

这将帮助您找出正确的问题。

【讨论】:

添加一个通用异常断点(缓存 Xcode 中的所有异常)是一个比将代码包装在 try catch 中更好的解决方案。

以上是关于子类化 UIApplication 以覆盖 sendEvent 导致崩溃的主要内容,如果未能解决你的问题,请参考以下文章

iPhone:覆盖 UIButton buttonWithType 以返回子类

在 QIODevice 子类中覆盖 readData 会返回不正确的结果

Swift 子类化 - 如何覆盖 Init()

子类化 UIButton 并覆盖触摸事件 - 不起作用

子类化 UIToolbar 并覆盖 drawRect: - UIBarButtonItems 不显示

子类化和覆盖使用 nib 文件创建的 UIView