我无法调试/使我的应用程序崩溃。 OTOH Crashlytics iOS 为某些用户报告了一些现场崩溃:NSInvalidArgumentException

Posted

技术标签:

【中文标题】我无法调试/使我的应用程序崩溃。 OTOH Crashlytics iOS 为某些用户报告了一些现场崩溃:NSInvalidArgumentException【英文标题】:I can't debug/make my app crash. OTOH Crashlytics iOS reports some crashes in-field for some users: NSInvalidArgumentException 【发布时间】:2017-02-20 16:54:00 【问题描述】:

多年来,我一直在用 Objective-C/ios 编写典型的随机代码。

今天,与我打交道的一位客户提出了这个看似无辜的 Crashlytics 崩溃:

Fatal Exception: NSInvalidArgumentException 
0  CoreFoundation 0x193b0e1c0 \__exceptionPreprocess 
1  libobjc.A.dylib 0x19254855c objc_exception_throw 
2  CoreFoundation 0x193b15278 \__methodDescriptionForSelector 
3  CoreFoundation 0x193b12278 \___forwarding___ 
4  CoreFoundation 0x193a0c59c _CF_forwarding_prep_0 
5  MyProjectTargetName 0x100087518 -[BannerContainer pressed:] (BannerContainer.m:105)
6  UIKit 0x199f3059c -[UIGestureRecognizerTarget _sendActionWithGestureRecognizer:] 
7  UIKit 0x199f33ca4 _UIGestureRecognizerSendTargetActions 
8  UIKit 0x199af52e8 _UIGestureRecognizerSendActions 
9  UIKit 0x199993828 -[UIGestureRecognizer _updateGestureWithEvent:buttonEvent:] 
10 UIKit 0x199f23ce8 _UIGestureEnvironmentUpdate
...

问题是,在第 105 行,在 BannerContainer.m “Bannercontainerpressed:”IBAction 内部,有一个显然很简单的分配:

if(self.banners==nil || [self.banners count]==0)
    
        return;
    

    NSInteger position=self.currentPosition; // both NSIntegers

    if(IS_IPAD) // Macro working perfectly as of today
    
        position=((UIButton *)sender).tag;  // this is offending line 105
    

根据 Crahslytics 的说法,NSInvalidArgumentException 在第 105 行崩溃......但我无法在那里识别任何“无效参数”。相反,我会说它只是一个按钮,它的 (NSInteger) 标签属性被分配给一个 NSInteger 变量(发送者总是一个按钮,因为这个函数链接到 .xib 文件中的 5 个 UIButtons)。这 5 个按钮有 5 个不同的标签(0、1、2、3 和 4)。如果 sender 为 nil,则该行甚至不会崩溃(我在 5 分钟前手动将 sender 设置为 nil 以检查此声明)。

无论如何,问题是我从来没有让我的应用程序在这条线上崩溃,显然 crashlytics 说一些现场人员已经能够做到。

我有点不知所措。有什么提示吗?有人可以指导我完成任何橡皮鸭调试吗?为什么 Crashlytics 能够找到我在开发环境中找不到的崩溃条件?

您好。

编辑:我无权访问该 Crashlytics 帐户。我发布的这个崩溃只是我的客户通过电子邮件发送给我们的 .txt 转储。我的客户 iTunes Connect 帐户既没有也没有访问此应用程序生产环境服务器的权限。我只是将我的代码交付给我的客户,然后他使用他的帐户编译、签名和上传所有内容。

【问题讨论】:

@Issac 你确定总是发件人是 UIButton 吗? 此 IBAction 仅链接到 xib 内的 5 个 UIButton。我看不出发件人如何/为什么不应该是 UIButton。我的问题是我不能让这条线崩溃(!!)我想(显然 Crashlytics 说有时可以) 你能检查发件人是否是 UIButton 然后进行分配吗?这必须修复你的崩溃,如果不是 UIButton 则发送 crashlytics 错误,以检查发生了什么 我没有崩溃,这是我的问题。我真的很想在我的开发机器上安装一个,但崩溃只出现在产品的生产版本中,在现场,在我客户的 Crashlytics 帐户中(我无法访问的帐户,他只给我这个我在上面发布的 .txt 转储)。 是的,我知道我可以在 UIButton.tag 分配之前放置一个“如果”,但我不能说我的客户:“我认为我已经修复了一些东西”,而没有检查是否真的我实际上已经修复了它,因为对我来说它并没有崩溃。 “我需要让它崩溃”。作为测试,我在标签分配上方输入了“sender = [[UIColor alloc] init];”,然后它崩溃了,但是使用“无法识别的选择器”,而不是 Crashlytics “NSInvalidArgumentException”...跨度> 【参考方案1】:

问题“已解决”(虽然不能肯定!!)。

嗯,正如调试中所预料的那样,sender 似乎不是 UIButton。 显然,当我的应用程序在 crashlytics 下崩溃时,这是因为发件人实际上是一个“UITapGestureRecognizer”(正如你们中的一些人指出的那样,可以从调试中扣除)。

但也发生了更多事情:我的客户向我发送了有关他的 crashlytics crash.txt 转储的更好信息,也就是说,他告诉我出现在他的 Crashlytics Web 界面的其他一些行中的其他信息,这些行让我查看其他代码我的应用程序的某些部分(过去是另一个人编写的一些代码),这导致我找到正确的冲突行。

查看这些新的代码部分和文件后,我终于发现有人在该控制器生命周期的其他地方“在我的按钮上”(以某种方式说)注册轻击手势。这些手势被分配了相同的“按下按钮”IBAction 函数,而不是我为 IB 中的真实按钮链接的函数。

这在我的应用程序的 iPhone 版本中是有意义的(我们没有按钮,而是视图,因此我们需要在它们之上捕获手势),但与我的应用程序的 ipad 版本重叠(crashlytics 崩溃一个),它有按钮来捕捉点击。

因此,为了解决这种情况,我刚刚删除了选择器注册线以用于点击手势,并且在此控制器初始化时不再注册点击手势(所有这些都在 ipad 模式下)。

从今天开始,Crashlytics 应该不会再因此而崩溃,但我要等几周后才能确定,一旦这个版本发布。

而且,我仍然无法亲手让这段错误的代码崩溃,所以我的担心仍然没有 100% 得到缓解。我非常确定我已经解决了它,但我并不觉得完全胜利。

问候并感谢您的帮助和分析。

【讨论】:

以上是关于我无法调试/使我的应用程序崩溃。 OTOH Crashlytics iOS 为某些用户报告了一些现场崩溃:NSInvalidArgumentException的主要内容,如果未能解决你的问题,请参考以下文章

线程中的网络请求使我的应用程序崩溃

导航抽屉:fragmentTransaction.commit() 使我的应用程序崩溃

传入的通知使我的应用程序 Android 崩溃

为啥 ntdll.dll 会使我的 c++ 可执行文件崩溃?

QRCodeReaderView 库使我的 android 应用程序崩溃

c ++我在Windows操作系统上获取文件创建日期的方法使我的控制台应用程序崩溃