在 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)
}
}
}
我正在尝试使用 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)
}
}
}