返回bool的方法中的错误/异常处理

sai*_*esh 10 objective-c nserror nsexception ios ios-frameworks

在我的自定义框架中,我有一个如下所示的方法,它从字典中获取值并将其转换为BOOL并返回布尔值.

- (BOOL)getBoolValueForKey:(NSString *)key;
Run Code Online (Sandbox Code Playgroud)

如果此方法的调用者传递了不存在的键,该怎么办?我应该抛出一个自定义的NSException,说密钥不存在(但是在目标c中不建议抛出异常)或者将NSError参数添加到此方法中,如下所示?

- (BOOL)getBoolValueForKey:(NSString *)key error:(NSError **)error; 
Run Code Online (Sandbox Code Playgroud)

如果我使用NSError,我将不得不返回'NO',这将是误导,因为'NO'可以是任何有效密钥的有效值.

Rob*_*ier 4

此 API 是由 长期建立的NSUserDefaults,并且应该是您设计 API 的起点:

- (BOOL)boolForKey:(NSString *)defaultName;
Run Code Online (Sandbox Code Playgroud)

如果布尔值与用户默认值中的 defaultName 关联,则返回该值。否则,返回NO。

除非有充分的理由,否则您应该避免创建不同的 API 来从密钥库中获取布尔值。在大多数 ObjC 接口中,获取不存在的键会返回nil并被nil解释为NO布尔上下文。

传统上,如果想要区分NOnil,则调用objectForKey以检索NSNumber并检查nil。同样,这是许多 Cocoa key store 的行为,不应轻易改变。

但是,可能有充分的理由违反此预期模式(在这种情况下,您绝对应该在文档中仔细注意它,因为它令人惊讶)。在这种情况下,有几种成熟的模式。

首先,您可以将获取未知密钥视为编程错误,并且您应该抛出异常,并期望程序很快就会因此崩溃。为此创建新类型的异常是非常不寻常的(也是意外的)。你应该提出NSInvalidArgumentException哪个问题恰好存在。

其次,可以通过正确使用方法来区分nil和。您的方法以 开头,但它不应该以 开头。在 Cocoa 中意味着“通过引用返回”,你可以这样使用它。像这样的东西:NOgetgetget

- (BOOL)getBool:(BOOL *)value forKey:(NSString *)key {
    id result = self.values[key];
    if (result) {
        if (value) {
            // NOTE: This throws an exception if result exists, but does not respond to 
            // boolValue. That's intentional, but you could also check for that and return 
            // NO in that case instead.
            *value = [result boolValue]; 
        }
        return YES;
    }

    return NO;
}
Run Code Online (Sandbox Code Playgroud)

这需要一个指向 bool 的指针,如果该值可用则填充它,然后返回YES。如果该值不可用,则返回NO

没有理由参与NSError。这增加了复杂性,但没有提供任何价值。即使您正在考虑 Swift 桥接,我也不会使用NSError此处来获取throws. 相反,您应该围绕此返回的方法编写一个简单的 Swift 包装器Bool?。这是一种更强大的方法,并且在 Swift 端使用起来更简单。