了解crashlytics UIKit错误



我很难理解我收到的UIKit崩溃报告:

有没有一种方法可以找出是哪行代码导致了这种情况:

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

错误本身是:

崩溃:com.apple.main-read

EXC_BAD_ACCESS KERN_INVALID_ADDRESS 0x0000000000000010

编辑:

根据下面的答案,我想知道是否应该使用:

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

并且总是呼叫

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

在我的应用程序中,我现在有自我的任何地方。解雇(动画:真,完成:零)?

这是一个必要的检查吗?或者我如何确定self.dismiss的问题所在?

一些解雇样本:

@IBAction func returnToDash(_ sender: UIButton) {
self.dismiss(animated: true, completion: nil)
}
let pending = UIAlertController(title: "nnn(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)
}
}
}
}

其中显示ActivityAlertWithCompletion2类似于:

public func displayActivityAlertWithCompletion2(ViewController: UIViewController, pending: UIAlertController, completionHandler: @escaping ()->())
{
//let pending = UIAlertController(title: "nnn"+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)
}

编辑2:

我的应用程序中的一些示例popover方法:

@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)
}
}

和搜索弹出窗口:

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)
}
}

您将无法从这次崩溃中找到代码行。但是,当用于调用dismiss(animated:completion:)的视图控制器在动画完成之前从视图层次结构中删除时,会发生此崩溃。

根据代码的设置方式,您可以尝试请求更高级别的视图控制器来调用解雇。另一个解决方案可能是将视图控制器保留在一个属性中,直到您确定完成它

编辑:1/15/18

作为对评论的回应,这里有一个示例,说明如何为记录事件并驳回的视图控制器创建函数。

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)
}
}

我不完全熟悉Crashlytics或他们的API,所以如果这个日志记录给你带来了问题,你可以查看这些链接。

  • https://docs.fabric.io/apple/crashlytics/enhanced-reports.html#custom-登录swift
  • 如何使用Crashlytics登录Swift

我也不知道他们是如何向您提供数据的,所以我无法向您解释解析数据的最佳方法。然而,时间戳肯定可以成功地用作最终解决方案。你也可以尝试给他们的支持发电子邮件,询问将这些日志映射到崩溃的最佳方式。

var topController: UIViewController = UIApplication.sharedApplication().keyWindow!.rootViewController!

这么多感叹号应该会告诉你这个代码有什么不好的地方。保护和检查这些假设,因为其中任何一个都可能爆炸。

除此之外,如果你像在Helper_StatusCheck.doSync中那样,将这些驳回/弹出/呈现操作作为延迟块的一部分,会出现一些非常奇怪的错误。导航堆栈可能会有各种各样的更改,您的假设可能不成立。

最新更新