Crashlytics report from exception in framework

2019-07-31 16:49发布

I have an app and two app extensions (keyboard and iMessage extensions) that use three frameworks which we built. The frameworks are part of the project and each have their own target. The app and the extensions link in these frameworks and we use them to perform common tasks like accessing a database.

If we have Crashlytics initialized in the AppDelegate like this

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool
{
    Fabric.with([Crashlytics.self])

    ... more
}

Then it ought to report crashes even if the crash occurred in one of the linked frameworks, right? If the dSYM files for the app, the app extensions, and the frameworks are present then it should be able to symbolicate the crash even into the framework code, correct?

I'm having some difficulties getting crashlytics to report on things reliably. If I put Crashlytics.sharedinstance().crash() into a function in main line code then it appears to work just fine. But if I call a function from a UIAlertAction like this...

@objc func onPreviewLongPress(_ notification : Notification)
{
    if let userInfo = notification.userInfo, let collectionName = userInfo["collectionName"] as! String? {
        let alert = UIAlertController(title: "", message: "Enter the code:", preferredStyle: .alert)
        alert.addTextField { (textField) in
            textField.text = ""
        }
        alert.addAction(UIAlertAction(title: "Cancel", style: .default, handler: nil))
        alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (_) in
            let textField = alert.textFields![0]
            // original code snipped
            if textField.text!.doesContain("crash") {
                self.callForCrash()
            }
        }))
        self.present(alert, animated: true, completion: nil)
    }
}

private func callForCrash() {
    Crashlytics.sharedInstance().crash() // DOES NOT REPORT!!!
}

I also tried forcing a crash by forcing division by zero...

private func callForCrash() {
    let nom = 12;
    let result = nom / zeroNum(13)
    print(result)
}
// separate function to allow division by zero to get through swift parsing
private func zeroNum(_ num: Int) -> Int {
    return num - num;
}

This also does not report. If, however I just put the Crashlytics.sharedInstance().crash() into the code just before the Alert, then it gets reported just fine.

@objc func onPreviewLongPress(_ notification : Notification)
{
    if let userInfo = notification.userInfo, let collectionName = userInfo["collectionName"] as! String? {
        let alert = UIAlertController(title: "", message: "Enter the code:", preferredStyle: .alert)
        alert.addTextField { (textField) in
            textField.text = ""
        }

        Crashlytics.sharedInstance().crash() // REPORTS JUST FINE HERE!
        // of course we don't see the alert box in this case

        alert.addAction(UIAlertAction(title: "Cancel", style: .default, handler: nil))
        alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (_) in
            let textField = alert.textFields![0]
            if textField.text!.doesContain("crash") {
                self.delayedCrash()
            }
        }))
        self.present(alert, animated: true, completion: nil)
    }
}

I have been over the installation process and the sample code many times over the last couple days.

  • The console shows the version I'm trying to test including the brand new build number
  • The console is not reporting issues with missing dSYM files,
  • I don't have bitcode enabled,
  • I am building 'active architecture only'=Yes (I also tried setting that to No),
  • The run script is present for the app and the two app extensions (I haven't tried testing an extension yet)
  • I have tried running from Xcode then stopping to launch after install,
  • I have also tried creating ad-hoc build and installing via the devices window (Xcode 9.2)
  • I'm triggering the crash and then re-launching the app so it will report

Can anyone see what I might have missed? I read something about arm64 being an issue but that was rather old so I'm not sure if that's still an issue. Is there something I can look for in the log that will tell me if it's working or not? UPDATE Is it possible that having both the Android and the iOS versions of the app using the same id i.e. 'com.mydomain.myapp' could cause some unpredictable behavior? It shows separately on the Fabric console.

TIA, Mike

1条回答
我只想做你的唯一
2楼-- · 2019-07-31 17:10

I'm going to go ahead and post this as an answer because it does appear to report crashes that happen in frameworks which was the primary point. It's only a partial answer because I was also talking about app extension. I have received reports from the keyboard extension but nothing from the iMessage extension so far.

Anyway, it does appear to work with frameworks. I took one of the frameworks we built and added these functions:

public static func doCrash() {
    func1()
}

private static func func1() {
    func2()
}

private static func func2() {
    let _ = 10 / prepNum(5)
}

private static func prepNum(_ int:Int) -> Int {
    return int - int
}

When the division by zero is hit the app crashed and, after I restarted it, I got the crash report with the following:

libswiftCore.dylib  
specialized _fatalErrorMessage(_:_:file:line:flags:) + 124
1   CommonKit _T012CommonKit9LocalFileC5func233_BC978A475DDB24483E4F12A335D91E70LLyyFZ + 136
2   CommonKit _T012CommonKit9LocalFileC5func133_BC978A475DDB24483E4F12A335D91E70LLyyFZ + 20
3   CommonKit _T012CommonKit9LocalFileC7doCrashyyFZ + 20
4   MyApp   StickerViewController.swift line 369
    StickerViewController.callFrameworkForCrash() -> ()

So it doesn't appear to be able to fully symbolicate the crash into the framework. But if we look at the results _T012CommonKit9LocalFileC7doCrashyyFZ we can pull out the name of the function that crashed CommonKit::LocalFile.doCrash().

I hope this helps out for someone in the future. I'll keep trying to get something from it in the iMessage extension.

Mike

查看更多
登录 后发表回答