首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Swift中捕捉NSKeyedUnarchiver "NSInvalidUnarchiveOperationException“?

如何在Swift中捕捉NSKeyedUnarchiver "NSInvalidUnarchiveOperationException“?
EN

Stack Overflow用户
提问于 2018-08-11 16:49:46
回答 3查看 1.2K关注 0票数 1

我在Swift中使用CodableNSKeyedArchiverNSKeyedUnarchiver来对对象进行内毒素/解码。

当编码的对象与预期的格式匹配时,事情会很顺利。但是,如果数据无效或格式不匹配,则在使用XCTest进行单元测试时将得到以下断言:

失败:捕捉到"NSInvalidUnarchiveOperationException",“数据无法读取,因为它的格式不正确。”

我正在使用NSKeyedUnarchiver.decodeTopLevelDecodable方法,在解码失败时使用它应该抛出一个异常

如果存档不是有效的属性列表,则此方法引发DecodingError.dataCorrupted(_:)错误。如果存档中的值无法解码,则此方法将引发相应的错误。

我很难捕捉到这个异常,因为try?do/catchXCTAssertThrowsError似乎都不起作用。

测试失败时的完全错误消息:

代码语言:javascript
复制
failed: caught "NSInvalidUnarchiveOperationException", "The data couldn’t be read because it isn’t in the correct format."
(
    0   CoreFoundation                      0x00007fff315f12db __exceptionPreprocess + 171
    1   libobjc.A.dylib                     0x00007fff587a1c76 objc_exception_throw + 48
    2   Foundation                          0x00007fff3376b077 -[NSCoder(Exceptions) __failWithExceptionName:errorCode:format:] + 0
    3   Foundation                          0x00007fff3376b371 -[NSCoder(Exceptions) __failWithExternalError:] + 161
    4   libswiftFoundation.dylib            0x0000000109872453 _T0So17NSKeyedUnarchiverC10FoundationE23decodeTopLevelDecodablexSgxm_SS6forKeytKs0G0RzlF + 403
    5   MBOUtilityKit                       0x0000000104cba964 _T013MBOUtilityKit17KeyedLocalStorageV3getxSS3key_tKs9DecodableRzs9EncodableRzlF + 772
    6   MBOUtilityKitTests macOS            0x0000000104c5144c _T024MBOUtilityKitTests_macOS017KeyedLocalStorageC0C17testDecodeFailureyyKF + 556
    7   MBOUtilityKitTests macOS            0x0000000104c51835 _T024MBOUtilityKitTests_macOS017KeyedLocalStorageC0C17testDecodeFailureyyKFTo + 69
    8   CoreFoundation                      0x00007fff31568bec __invoking___ + 140
    9   CoreFoundation                      0x00007fff31568ac0 -[NSInvocation invoke] + 320
    10  XCTest                              0x000000010036c90d __24-[XCTestCase invokeTest]_block_invoke_2.187 + 65
    11  XCTest                              0x00000001003d6207 -[XCTMemoryChecker _assertInvalidObjectsDeallocatedAfterScope:] + 51
    12  XCTest                              0x00000001003755ef -[XCTestCase assertInvalidObjectsDeallocatedAfterScope:] + 116
    13  XCTest                              0x000000010036c89c __24-[XCTestCase invokeTest]_block_invoke.181 + 210
    14  XCTest                              0x00000001003c8772 +[XCTestCase(Failures) performFailableBlock:shouldInterruptTest:] + 36
    15  XCTest                              0x00000001003c86bc -[XCTestCase(Failures) _performTurningExceptionsIntoFailuresInterruptAfterHandling:block:] + 54
    16  XCTest                              0x000000010036c4db __24-[XCTestCase invokeTest]_block_invoke + 854
    17  XCTest                              0x00000001003cd659 -[XCUITestContext performInScope:] + 237
    18  XCTest                              0x000000010036c170 -[XCTestCase invokeTest] + 175
    19  XCTest                              0x000000010036dea6 __26-[XCTestCase performTest:]_block_invoke_2 + 42
    20  XCTest                              0x00000001003c8772 +[XCTestCase(Failures) performFailableBlock:shouldInterruptTest:] + 36
    21  XCTest                              0x00000001003c86bc -[XCTestCase(Failures) _performTurningExceptionsIntoFailuresInterruptAfterHandling:block:] + 54
    22  XCTest                              0x000000010036dd53 __26-[XCTestCase performTest:]_block_invoke.326 + 90
    23  XCTest                              0x00000001003d24a1 +[XCTContext runInContextForTestCase:block:] + 225
    24  XCTest                              0x000000010036d454 -[XCTestCase performTest:] + 673
    25  XCTest                              0x00000001003b0555 -[XCTest runTest] + 57
    26  XCTest                              0x0000000100368b30 __27-[XCTestSuite performTest:]_block_invoke + 365
    27  XCTest                              0x000000010036830c -[XCTestSuite _performProtectedSectionForTest:testSection:] + 55
    28  XCTest                              0x00000001003685cd -[XCTestSuite performTest:] + 296
    29  XCTest                              0x00000001003b0555 -[XCTest runTest] + 57
    30  XCTest                              0x0000000100368b30 __27-[XCTestSuite performTest:]_block_invoke + 365
    31  XCTest                              0x000000010036830c -[XCTestSuite _performProtectedSectionForTest:testSection:] + 55
    32  XCTest                              0x00000001003685cd -[XCTestSuite performTest:] + 296
    33  XCTest                              0x00000001003b0555 -[XCTest runTest] + 57
    34  XCTest                              0x0000000100368b30 __27-[XCTestSuite performTest:]_block_invoke + 365
    35  XCTest                              0x000000010036830c -[XCTestSuite _performProtectedSectionForTest:testSection:] + 55
    36  XCTest                              0x00000001003685cd -[XCTestSuite performTest:] + 296
    37  XCTest                              0x00000001003b0555 -[XCTest runTest] + 57
    38  XCTest                              0x00000001003e6308 __44-[XCTTestRunSession runTestsAndReturnError:]_block_invoke + 40
    39  XCTest                              0x000000010038aaa4 -[XCTestObservationCenter _observeTestExecutionForBlock:] + 600
    40  XCTest                              0x00000001003e610e -[XCTTestRunSession runTestsAndReturnError:] + 369
    41  XCTest                              0x000000010034f865 -[XCTestDriver runTestsAndReturnError:] + 440
    42  XCTest                              0x00000001003d10f3 _XCTestMain + 1228
    43  xctest                              0x0000000100002155 main + 557
    44  libdyld.dylib                       0x00007fff593bb015 start + 1
    45  ???                                 0x0000000000000005 0x0 + 5
)
EN

回答 3

Stack Overflow用户

发布于 2019-05-23 20:39:50

因为iOS 9,您可以使用:unarchiveTopLevelObjectWithData(_:),它会引发异常。

示例:

代码语言:javascript
复制
try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data)

https://developer.apple.com/documentation/foundation/nskeyedunarchiver/2919664-unarchivetoplevelobjectwithdata

票数 4
EN

Stack Overflow用户

发布于 2018-08-11 16:57:50

该类的Objective桥没有正确设置以在Swift中抛出错误,因此您必须创建一个客观-C包装器来抛出或捕获错误。

以下是我的超级简单的“SafeUnarchiver”,您可以从中启发自己:

SafeUnarchiver.h.h:

代码语言:javascript
复制
#import <Foundation/Foundation.h>

@interface SafeUnarchiver : NSObject
+(NSObject* _Nullable)unarchive:(NSData* _Nonnull)data;
@end

SafeUnarchiver.m.m:

代码语言:javascript
复制
#import "SafeUnarchiver.h"

@implementation SafeUnarchiver
+(NSObject *)unarchive:(NSData *)data {
    @try {
        id object = [NSKeyedUnarchiver unarchiveObjectWithData:data];
        return object;
    } @catch (NSException *exception) {
        NSLog(@"ERROR attempting to unarchive object: %@", exception);
    }
    return nil;
}
@end

不要忘了向苹果公司提交一张雷达罚单,这样他们最终就能解决这一异常,而不被正确地捕捉到。

按照您希望从Swift访问的其他目标-C代码,您必须将标题添加到您的-桥接-Header.h中。

票数 2
EN

Stack Overflow用户

发布于 2019-06-26 10:28:36

您需要像这样设置未存档程序失败策略:

代码语言:javascript
复制
let unarchiver = NSKeyedUnarchiver(forReadingWith: data)
unarchiver.decodingFailurePolicy = .setErrorAndReturn

这将使NSKeyedUnarchiver返回NSError,它将被正确地转换为您能够捕捉到的快速异常。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51801808

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档