Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding crashlytics UIKit errors

I am having trouble understanding the UIKit crash reports that I am receiving:

Is there a way of finding out what line of code caused this:

Crashed: com.apple.main-thread
0  UIKit                          0x195694264 __56-[UIPresentationController runTransitionForCurrentState]_block_invoke + 444
1  UIKit                          0x1955d0950 _runAfterCACommitDeferredBlocks + 292
2  UIKit                          0x1955c29ec _cleanUpAfterCAFlushAndRunDeferredBlocks + 528
3  UIKit                          0x195336648 _afterCACommitHandler + 132
4  CoreFoundation                 0x18f1c09a8 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 32
5  CoreFoundation                 0x18f1be630 __CFRunLoopDoObservers + 372
6  CoreFoundation                 0x18f1bea7c __CFRunLoopRun + 956
7  CoreFoundation                 0x18f0eeda4 CFRunLoopRunSpecific + 424
8  GraphicsServices               0x190b58074 GSEventRunModal + 100
9  UIKit                          0x1953a9058 UIApplicationMain + 208
10 FlexConnect                    0x1001b48c8 main (AppDelegate.swift:20)
11 libdyld.dylib                  0x18e0fd59c start + 4

The error itself is:

Crashed: com.apple.main-thread

EXC_BAD_ACCESS KERN_INVALID_ADDRESS 0x0000000000000010

EDIT:

Based of the answer below, I'm wondering if it is advisable to use:

func topMostController() -> UIViewController {
    var topController: UIViewController = UIApplication.sharedApplication().keyWindow!.rootViewController!
    while (topController.presentedViewController != nil) {
        topController = topController.presentedViewController!
    }
    return topController
}

and always call

let topVC = topMostController().dismiss(animated: true, completion: nil)

everywhere in my app where I currently have self.dismiss(animated: true, completion: nil)?

Is this a necessary check or how can I pin down where self.dismiss is having an issue?

Some sample dismissals:

@IBAction func returnToDash(_ sender: UIButton) {
     self.dismiss(animated: true, completion: nil)
}

let pending = UIAlertController(title: "\n\n\n\(title)", message: nil, preferredStyle: .alert)
displayActivityAlertWithCompletion2(ViewController: self, pending: pending){_ in
   Helper_StatusCheck.doSync(_cleanSync: false){
        Prefs.is_Syncing = false
        DispatchQueue.main.async {
            pending.dismiss(animated: true){
                   Toast(text: "Upload sync completed").show()
                   self.dismiss(animated: true, completion: nil)
            }
        }
   }
}

where displayActivityAlertWithCompletion2 looks like:

public func displayActivityAlertWithCompletion2(ViewController: UIViewController, pending: UIAlertController, completionHandler: @escaping ()->())
{
    //let pending = UIAlertController(title: "\n\n\n"+title, message: nil, preferredStyle: .alert)
    //create an activity indicator
    let indicator = UIActivityIndicatorView(frame: pending.view.bounds)
    indicator.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    indicator.color = UIColor(rgba: Palette.loadingColour)
    //add the activity indicator as a subview of the alert controller's view
    pending.view.addSubview(indicator)
    indicator.isUserInteractionEnabled = false
    // required otherwise if there buttons in the UIAlertController you will not be able to press them
    indicator.startAnimating()



    ViewController.present(pending, animated: true, completion: completionHandler)
}

EDIT 2 :

Some sample popover methods in my app:

 @IBAction func search(_ sender: UIButton) {
        if let popView = UIStoryboard(name: "AssetCommon", bundle: nil).instantiateViewController(withIdentifier: "searchPop") as? searchPopVC {
            popView.delegate = self
            popView.modalPresentationStyle = .popover;
            popView.popoverPresentationController?.delegate = self
            popView.popoverPresentationController?.barButtonItem = searchButton
            popView.popoverPresentationController?.permittedArrowDirections = .any
            popView.preferredContentSize = CGSize(width: 300, height: 70)
            self.present(popView, animated: true, completion: nil)
        }
    }

and search pop:

class searchPopVC: UIViewController
{
    @IBOutlet weak var searchBar: UISearchBar!

    weak var delegate: SearchPopDelegate?

    override func viewDidLoad()
    {
        super.viewDidLoad()

        searchBar.delegate = self;
    }

    override func didReceiveMemoryWarning()
    {
        super.didReceiveMemoryWarning()
    }

    @IBAction func performSearch(_ sender: UIButton)
    {
        let term = searchBar.text ?? "";
        delegate?.performSearch(with: term)
        self.dismiss(animated: true, completion: nil);
    }
}

extension searchPopVC: UISearchBarDelegate
{
    func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
        let term = searchBar.text ?? "";
        delegate?.performSearch(with: term);
        self.dismiss(animated: true, completion: nil)
    }
}
like image 475
user2363025 Avatar asked Oct 10 '17 09:10

user2363025


1 Answers

You won't be able to find the line of code from this crash. However, this crash happens when the view controller you use to call dismiss(animated:completion:) is removed from the view hierarchy prior to the animation completing.

Depending on how your code is setup, you can try to request a view controller higher up to call the dismissal. Another solution could be to retain the view controller in a property until your for sure done with it.

Edit: 1/5/18

In response to the comments, here is an example of how a function can be made for view controllers that logs an event and dismisses.

extension UIViewController {
    func dismissAndLog(animated: Bool, completion: (() -> ())? = nil) {
        // Here are two examples of how your view controller can be identified.
//        let id = title
        let id = String(describing: type(of: self))
        CLSLogv("Dismissed View Controller: %@", getVaList([id]))

        dismiss(animated: animated, completion: completion)
    }
}

I'm not entirely familiar with Crashlytics or their API, so if this logging is giving you issues, you can check out these links.

  • https://docs.fabric.io/apple/crashlytics/enhanced-reports.html#custom-logging-in-swift
  • How to use Crashlytics logging in Swift?

Also I don't know how they provide the data to you, so I can't explain to you the best way to parse it. However certainly the timestamps can be successfully used as a final solution. You can also try emailing their support asking for the best way to map these logs to the crash.

like image 169
cnotethegr8 Avatar answered Nov 01 '22 04:11

cnotethegr8