我正在编写各种例程,我正在尽力保持整洁和重构。
我正在创建的方法开始看起来与此代码类似:
-(IBAction)buttonPress:(id)sender {
// Create Document Shopping List with this document
[self doSomething:&error];
if(error) {
[NSApp presentError:&error];
return nil;
}
[self doSomethingElse:&error];
if(error) {
[NSApp presentError:&error];
return nil;
}
[self doYetSomethingElse:&error];
if(error) {
[NSApp presentError:&error];
return nil;
}
}
我喜欢NSError,但这似乎是处理我所有错误的一种非常笨拙的方式。
我对替代方法有一些想法:
a)错误检查可以内置到doSomething,doSomethingElse等方法中,但是如果不对返回值进行某种检查,我将无法退出按钮按下方法,这会导致我回到类似的结构。
b)我可以将NSError设置为观察到的键值,但是这个问题感觉非常错误。我非常清楚KVO滥用的可能性,所以我试图在没有它的情况下做任何事情。
我肯定错过了一些非常基本的东西吗?有没有一种模式可以帮助我?或者这个结构好吗?
答案 0 :(得分:11)
我认为这里提出的答案都没有考虑到Apple推荐的做法。
基本上,您不应该检查NSError
对象以确定是否存在问题。通过检查从指向NSError
指针的方法返回的值来检查是否存在问题。
重要成功或失败由返回值表示 方法。虽然Cocoa方法间接返回错误对象 如果是,Cocoa错误域保证返回这样的对象 方法通过直接返回
nil
或NO
表示失败,您应该这样做 在尝试之前,请始终检查返回值是nil
还是NO
对NSError
对象做任何事情。
答案 1 :(得分:2)
您的问题的要点是您是否可以对错误处理进行结构性改进。我认为,通过基本上引入更多的嵌套层,可以通过将更多代码提取到单独的方法/函数中,或者通过在高级样本方法中引入嵌套来实现。
这个想法是,当涉及到处理大多数错误时,您可能要么对执行备用任务感兴趣,要么失败并将错误传播到链中,以便某些负责的控制器可以通过UI将错误传达给用户
使用“传播或处理”这个概念,我会像这样重写你的示例方法:
-(IBAction)buttonPress:(id)sender {
// Create Document Shopping List with this document
[self doSomething:&error];
if(error == nil) {
[self doSomethingElse:&error];
if (error == nil) {
[self doYetSomethingElse:&error];
}
}
if(error) {
[NSApp presentError:&error];
}
}
请注意,在特定方法中引入过多嵌套有很好的理由。像这样的嵌套本质上是提取方法的简短替代方案。例如,“doSomething:”本身调用doSomethingElse:来调用doYetSomethingElse:这可能更有意义。这将在代码上施加与if-nest相同的结构,但可以说更易于维护。
顺便说一句,我不是内联返回声明的粉丝。在这个特定的实例中,sample方法实际上并没有调用返回值,但如果确实如此,我更喜欢将局部变量设置为返回值,并且仅在流控制结束时返回。过早地跳出一个函数或方法是遇到奇怪错误的可靠方法,恕我直言。
答案 2 :(得分:1)
我认为真正的问题是您在错误处理中需要多少粒度。您的代码基本上是正确的 - 但是您可以通过不频繁地检查错误来清理事物,或者使用像他在NSException的答案中提到的像teabot这样的全能方法。许多返回错误的内置函数(如NSFileManager的moveItemAtPath :)除了提供NSError对象外还返回BOOL - 因此如果不需要NSError信息,也可以使用嵌套的if语句。
总而言之,实际上并没有很好的方法。如果您的代码很长,KVO可能是一个很酷的解决方案。我从来没有尝试过这样的情况。
答案 3 :(得分:0)
注意:当我发布这个时,我不知道任何MacOS / Cocoa异常辩论。当你考虑这个答案时,请记住这一点。
为什么不使用exceptions呢?这样您就可以省去方法中的错误参数,并在一个地方处理错误。
-(IBAction)buttonPress:(id)sender {
// Create Document Shopping List with this document
@try {
[self doSomething];
[self doSomethingElse];
[self doYetSomethingElse];
} @catch (NSException* e) {
[NSApp presentException:e];
}
return nil;
}
您当然需要在doXXXX方法中根据需要抛出异常:
NSException* e = [NSException exceptionWithName:@"MyException"
reason:@"Something bad happened"
userInfo:nil];
@throw e;