许多 Cocoa 方法采用一个可选NSError **
参数,用于报告错误。我经常发现自己使用这样的方法,即使在可能发生错误的唯一方法是通过我的编程错误而不是意外的运行时条件的情况下。因此,我不想编写任何错误处理代码来执行任何用户可见的事情。我真正想做的就是记录错误(可能还有崩溃),同时让我的代码尽可能简洁易读。
问题在于“保持代码简洁”和“记录错误”目标相互矛盾。我经常在这两种方法之间做出选择,我都不喜欢这两种方法:
1. 为错误指针参数传递 NULL。
[managedObjectContext save:NULL];
- 优点:简洁、易读,并且清楚地表明不会出现错误。只要我正确地相信这里的错误在逻辑上是不可能的,那就完全没问题了。
- 缺点:如果我搞砸了并且确实发生了错误,它不会被记录下来,我的调试会更加困难。在某些情况下,我什至可能没有注意到错误发生了。
NSError **
2.每次都使用相同的样板代码传递并记录产生的错误。
NSError *error;
[managedObjectContext save:&error];
if (error) {
NSLog(@"Error while saving: %@", error);
}
- 优点:错误不会静默传递——我会收到警告并提供调试信息。
- 缺点:它非常冗长。它写起来更慢,读起来更慢,而且当它已经嵌套在某些级别的缩进中时,我觉得它会使代码的可读性降低。通常这样做只是为了记录错误,并且习惯于在阅读时跳过样板文件,这也让我有时无法注意到我正在阅读的某些代码实际上对预期在运行时发生的错误有重要的错误处理块。
来自 Python、Java、PHP 和 Javascript 等语言的背景,我发现不得不编写 4 行额外的样板代码来获得通知类型的错误有点麻烦,在我习惯的语言中,我可以通过异常或警告找出相关信息,而无需编写任何明确检查错误的代码。
我最喜欢的是一些巧妙的 hack,我可以使用它来自动记录这些方法创建的错误,而无需在每个方法调用上编写样板,从而为我提供惰性 NULL 传递方法和错误的好处-记录样板。换句话说,我想这样写:
[managedObjectContext save:&magicAutologgingError];
并且知道如果该方法创建了一个NSError
,它会以某种方式神奇地被记录下来。
我不太确定该怎么做。我考虑过使用一个NSError
记录自身的子类dealloc
,但意识到由于我不负责实例化 Cocoa 的方法创建的错误对象,所以无论如何我的子类都不会被使用。我考虑过使用方法调配让所有 NSError
s 都像这样登录dealloc
,但我不确定这是否真的可取。我考虑过使用某种观察者类来监视内存中给定的常量空间,我可以将其用于NSError
要记录的指针,但据我所知,没有办法像 KVO 那样观察内存中的任意空间,所以除了有一个重复检查要记录的错误的线程之外,我看不到实现这一点的方法。
谁能看到实现这一目标的方法?