【问题标题】:Swift 3: How to catch error if NSCoder decodeX function decodes wrong value type?Swift 3:如果 NSCoder decodeX 函数解码错误的值类型,如何捕获错误?
【发布时间】:2016-09-24 01:06:51
【问题描述】:

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

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

let value = decodeInteger(forKey key: TestKey)

但是如果从decodeInteger 返回的值是StringBoolInt 以外的其他值呢?

或者如果 TestKey 实际上没有映射,因为它包含错误的键数据怎么办?

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

【问题讨论】:

  • @LeoDabus 0 是一个有效的整数。如何区分 0 的有效和无效情况?

标签: swift swift3


【解决方案1】:

在非整数键上使用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 代码中实现。

【讨论】:

  • 所以说这比 Swift 2 更糟糕,让你捕捉到这样的错误是不正确的:if let value = aDecoder.decodeObjectForKey(TestKey) as? Bool { test = value }
  • 我没有 Xcode 7 来测试它,但如果它确实适用于 Swift 2,那么是的,Swift 3 让它变得更糟。这并不是 Swift 3 唯一让事情变得更糟的事情。指针在 Swift 2 中是一个痛点,在 Swift 3 中是一个更大的痛点
  • 与您的问题无关。如果您处理使用指针的 C 库,那么在 Swift 中与它们交互是一件很痛苦的事情
猜你喜欢
  • 1970-01-01
  • 2021-11-15
  • 2022-11-19
  • 1970-01-01
  • 1970-01-01
  • 2017-01-24
  • 1970-01-01
  • 1970-01-01
  • 2016-01-25
相关资源
最近更新 更多