异常未被捕获

Exception is not being caught

Crashlytics 报告以下行 有时 抛出 NSInternalInconsistencyException:

let attrStr = try NSMutableAttributedString(
        data: modifiedFont.data(using: String.Encoding.unicode, 
        allowLossyConversion: true)!,
        options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding: String.Encoding.utf8.rawValue],
        documentAttributes: nil)

在这里,我对 为什么 会发生这种情况 (there's a 3 year old question about it) 并不像我对 catching/handling 这个异常感兴趣。我试过这样做:

do {
    let attrStr = try NSMutableAttributedString(
       data: modifiedFont.data(using: String.Encoding.unicode, allowLossyConversion: true)!,
       options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding: String.Encoding.utf8.rawValue],
       documentAttributes: nil)

     self.attributedText = attrStr
} catch {
    self.attributedText = nil
    self.text = text.stripHTML()
}

...但由于某种原因这不起作用 - 仍在报告异常。

我是否试图以正确的方式抓住它?到底能不能抓到?如果没有,我有什么选择?

我想当您尝试将 modifiedFont 转换为 Data 时会发生崩溃。
modifiedFont.data(using: String.Encoding.unicode, allowLossyConversion: true)! 如果将数据转换行移出 try-catch 范围,很可能会出现相同的错误。为了避免崩溃,不要使用force unwrap(!)。

如果在初始化 NSMutableAttributedString 期间抛出任何错误,则会被捕获。

Swift 将带有可空 returns 和尾随 NSError** 参数的 Objective-C 方法转换为抛出 Swift 的方法。但是,在 Objective-C 中,您也可以抛出异常。这些与 NSErrors 不同,Swift 不捕获它们。事实上,在 Swift 中没有办法捕捉到它们。您将不得不编写一个 Objective-C 包装器来捕获异常并以某种方式将其传回 Swift 可以处理。

您可以在 Apple 文档 Handling Cocoa Errors in SwiftHandle Exceptions in Objective-C Only 部分中找到它。

所以事实证明你 可以 抓住它,但值得考虑你是否应该(请参阅下面@Sulthan 的评论)。据我所知,大多数 Apple 框架都不是 exception-safe(请参阅:Exceptions and the Cocoa Frameworks),因此您不能只捕获异常并继续,就好像什么都没发生一样。你最好的选择是尽可能地保存并尽快退出。另一个需要考虑的问题是,除非您重新抛出异常,否则 Crashlytics 等框架不会将其报告给您。所以,如果你决定抓住它,你应该记录它 and/or 重新抛出它,这样你就知道它正在发生。

NSInternalInconsistencyException 是一个 Objective-C 异常,无法被 Swift 代码捕获。您只能使用 Objective-C 代码捕获此类异常,因此您需要创建一个 Objective-C 包装器以从 Swift 代码中捕获此异常,例如使用以下 Objective-C 方法:

+ (NSException *)tryCatchWithBlock:(void (^)(void))block {
    @try {
        block();
    } @catch (NSException *exception) {
        return exception;
    } @catch (id exception) {
        return [NSException exceptionWithName:NSGenericException reason:nil userInfo:nil];
    }
    return nil;
}

此方法是我名为 LSCategories 的库的一部分:https://github.com/leszek-s/LSCategories 具有各种有用的 categories/extensions 因此您还可以轻松地将此库与 CocoaPods 集成到您的 Swift 项目中,然后您可以通过像这样包装 swift 代码来捕获 NSInternalInconsistencyException:

let objcException = NSException.lsTryCatch {
    // put your swift code here
}

如果你想这样做,这就是你如何捕获这个异常。但更重要的是,您应该调查为什么在您的案例中会出现此异常。也许您正在后台线程上调用您的代码。