Swift 3:如果NSCoder decodeX函数解码错误的值类型,如何捕获错误?

Cra*_*lot 2 swift swift3

Swift 3改变了NSCoder的工作方式.

正如其他SO问题所提到的,要解码像Int或类似的值类型Bool,您必须使用特定的函数.例如,decodeInteger用于解码Int像这样的值:

let value = decodeInteger(forKey key: TestKey)
Run Code Online (Sandbox Code Playgroud)

但是如果返回的值decodeInteger是a String或者Bool除了a 之外的东西Int呢?

或者,如果TestKey实际上映射到什么都没有,因为它包含错误的密钥数据?

你如何优雅地捕捉到这些错误?

Cod*_*ent 5

使用decodeInteger一个非整数的关键将引发异常.可悲的是,它是NSExceptionSwift无法直接处理的(参见下面的参考资料).

您需要首先编写一个包装器来处理ObjC中的ObjC异常并将其桥接到Swift(受此答案的启发):

/// -------------------------------------------
/// ObjC.h
/// -------------------------------------------
#import <Foundation/Foundation.h>

@interface ObjC : NSObject

+ (BOOL)catchException:(void(^)())tryBlock error:(__autoreleasing NSError **)error;

@end

/// -------------------------------------------
/// ObjC.m
/// -------------------------------------------
#import "ObjC.h"

@implementation ObjC

+ (BOOL)catchException:(void(^)())tryBlock error:(__autoreleasing NSError **)error {
    @try {
        tryBlock();
        return YES;
    }
    @catch (NSException *exception) {
        NSMutableDictionary * userInfo = [NSMutableDictionary dictionaryWithDictionary:exception.userInfo];
        [userInfo setValue:exception.reason forKey:NSLocalizedDescriptionKey];
        [userInfo setValue:exception.name forKey:NSUnderlyingErrorKey];

        *error = [[NSError alloc] initWithDomain:exception.name
                                            code:0
                                        userInfo:userInfo];
        return NO;
    }
}

@end
Run Code Online (Sandbox Code Playgroud)

现在你可以在Swift中捕获异常了:

do {
    try ObjC.catchException {
        let age = aDecoder.decodeInteger(forKey: "firstName")
    }
} catch {
    print(error.localizedDescription)
}
Run Code Online (Sandbox Code Playgroud)

参考:使用ObjectiveC和Swift:采用Cocoa设计模式

虽然Swift错误处理类似于Objective-C中的异常处理,但它是完全独立的功能.如果Objective-C方法在运行时抛出异常,则Swift会触发运行时错误.无法直接在Swift中从Objective-C异常中恢复.必须在Swift使用的Objective-C代码中实现任何异常处理行为.