在 Swift 中捕获 Objective-C 异常

Catch Objective-C exception in Swift

我正在尝试使用 obj.setValue(value, forKey: key) 在我的 Swift 代码中设置 @objc 对象的值。

当对象设置了 属性 时它工作正常。但如果没有,我的应用程序会因未捕获 NSException ("class is not key value coding-compliant…").

而严重崩溃

我如何才能像在 Objective-C 中那样捕获并吸收此异常,以免使我的应用程序崩溃?我尝试将它包装在 Swift try-catch 中,但它抱怨说 none 的指令抛出并且什么都不做。

不幸的是,这不是我希望得到的答案:

Although Swift error handling resembles exception handling in Objective-C, it is entirely separate functionality. If an Objective-C method throws an exception during runtime, Swift triggers a runtime error. There is no way to recover from Objective-C exceptions directly in Swift. Any exception handling behavior must be implemented in Objective-C code used by Swift.

Excerpt From: Apple Inc. “Using Swift with Cocoa and Objective-C (Swift 2.1).” iBooks. https://itun.es/ca/1u3-0.l

我的下一个攻击计划是添加一个我可以调用的 Objective-C 函数,它将尝试包装在 @try/@catch 中。这真的很糟糕,Apple。

看到这个

//
//  ExceptionCatcher.h
//

#import <Foundation/Foundation.h>    

NS_INLINE NSException * _Nullable tryBlock(void(^_Nonnull tryBlock)(void)) {
    @try {
        tryBlock();
    }
    @catch (NSException *exception) {
        return exception;
    }
    return nil;
}

我想喊出这个问题给出的答案:

因为您仍然可以以自然的方式在调用中使用 Swift do/catch,因此仅次于 Swift 的最佳做法是实际捕获 ObjC 异常。

Swift 5 版本,实用程序错误类型:

NS_INLINE NSException * _Nullable ExecuteWithObjCExceptionHandling(void(NS_NOESCAPE^_Nonnull tryBlock)(void)) {
    @try {
        tryBlock();
    }
    @catch (NSException *exception) {
        return exception;
    }
    return nil;
}
public struct NSExceptionError: Swift.Error {

   public let exception: NSException

   public init(exception: NSException) {
      self.exception = exception
   }
}

public struct ObjC {

   public static func perform(workItem: () -> Void) throws {
      let exception = ExecuteWithObjCExceptionHandling {
         workItem()
      }
      if let exception = exception {
         throw NSExceptionError(exception: exception)
      }
   }
}