我从Swift调用了一些旧的Objective-C代码,它经常会抛出这个错误,即使看起来没有什么问题:
do {
try objCObject.someMethod()
}
catch {
print(error)
// Trying to handle the error here
}
其中该方法的Objective-C签名如下所示:
- (BOOL) someMethodWithError: (NSError **) outError;
在该catch
中放置一个断点,我可以通过使用LLDB控制台看到这一点。
(lldb) po error
Foundation._GenericObjCError.nilError
(lldb) po error as NSError
Error Domain=Foundation._GenericObjCError Code=0 "(null)"
这里发生了什么?我该如何处理?当我尝试在Swift中为此编写一个特例时,我得到了这样的结果:
/Path/To/My Code.swift:200:27: error: module 'Foundation' has no member named '_GenericObjCError'
catch Foundation._GenericObjCError.nilError {
^~~~~~~~~~ ~~~~~~~~~~~~~~~~~
发布于 2019-04-12 04:47:25
这是在Objective-C方法使用标准的Cocoa方法抛出错误时造成的:将NSError **
作为最后一个参数,并返回一个带有YES
的BOOL
,表示成功。如果这按预期工作,则只有在发生错误时返回值才会为NO
,然后会相应地设置NSError **
对象。
Swift expects this是所有带有此签名的Objective-C方法的工作方式。
您所看到的是当这些方法中的一个由于某种原因行为不正确并返回NO
而没有将NSError **
参数设置为任何值(或者显式设置为nil
)时会发生什么。
这可能是由于许多因素造成的,例如返回一个隐式转换为BOOL
的错误代码(因此,0
成功代码被转换为NO
失败代码),或者编写其返回行的方式使其逻辑在成功时并不总是返回YES
,或者因为实际上存在错误但作者不知道将NSError **
设置为什么,等等。
至于如何处理这个问题,以下是我要做的:
如果您不知道作者的意图,或者作者记录了这表示成功状态
在这种情况下,我认为最安全的做法是假设作者只是犯了一个错误并返回了错误的值。最好完全忽略抛出的错误。
do {
try objCObject.someMethod()
}
catch {
let nsError = (error as NSError)
if nsError.code == 0,
nsError.domain == "Foundation._GenericObjCError" {
print("Got invalid error from Objective-C")
}
else {
// Actually handle your error here
}
}
如果作者记录了这表示错误状态
在这种情况下,将其视为作者记录的错误。如果需要,您可以调整上面的示例代码以特殊处理此错误。
如果你是作者
这很简单。只需更改您的方法,使其仅在您处于实际错误状态时返回NO
,并始终确保已将NSError **
对象设置为有效的错误对象(如果调用者请求)。
- (BOOL) someMethodWithError: (NSError **) outError {
[self.something attempt];
if (!self.something.succeeded) {
if (nil != outError) {
*outError = [self makeSomeDescriptiveErrorFromSomething: self.something];
}
return NO;
}
else {
return YES;
}
}
https://stackoverflow.com/questions/55640917
复制相似问题