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

时间:2016-09-24 01:06:52

标签: swift swift3

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

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

let value = decodeInteger(forKey key: TestKey)

但如果decodeInteger返回的值是StringBoolInt以外的其他内容怎么办?

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

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

1 个答案:

答案 0 :(得分:5)

在非整数键上使用decodeInteger会引发异常。可悲的是,它是一个NSException,Swift无法直接处理(参见下面的参考资料)。

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

/// -------------------------------------------
/// 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

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

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

参考文献Using ObjectiveC with Swift: Adopting Cocoa Design Patterns

  

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