更简洁的方法来记录Objective-C中的错误

Mar*_*ery 7 cocoa cocoa-touch objective-c nserror

许多Cocoa方法采用可选NSError **参数来报告错误.通常,我发现自己使用这样的方法,即使在出现错误的唯一方法是通过编程错误而不是意外的运行时条件.因此,我不想编写任何可以执行任何用户可见事物的错误处理代码.我真正想要做的就是记录错误(也许是崩溃),同时保持我的代码尽可能简洁和可读.

问题在于"保持代码简洁"和"记录错误"目标彼此紧张.我经常在这两种方法之间做出选择,我不喜欢这两种方法:

1.为错误指针参数传递NULL.

[managedObjectContext save:NULL];
Run Code Online (Sandbox Code Playgroud)
  • 优点:简洁,易读,并且明确表示不会出现错误.只要我认为这里的错误在逻辑上是不可能的,我就完全没问题.
  • 缺点:如果我搞砸了并且确实发生了错误,它将不会被记录,我的调试将更加困难.在某些情况下,我甚至可能没有注意到错误发生了.

2. NSError **每次都传递并记录结果错误,并使用相同的样板代码.

NSError *error;
[managedObjectContext save:&error];
if (error) {
    NSLog(@"Error while saving: %@", error);
}
Run Code Online (Sandbox Code Playgroud)
  • 优点:错误不会以静默方式传递 - 我被提醒他们并给出调试信息.
  • 缺点:它非常冗长.写入速度慢,读取速度慢,当它嵌入某些级别的缩进时,我觉得它使代码的可读性降低.通常这样做仅仅是为了记录错误,并且习惯于在阅读时跳过样板文件,这也使我有时无法注意到我正在阅读的某些代码实际上是否存在对运行时预期会发生的错误的重要错误处理块.

来自Python,Java,PHP和Javascript等语言的背景,我发现必须编写4行额外的样板才能获得有关错误类型的通知,在我习惯的语言中,我有点麻烦通过异常或警告找出,而不必编写任何明确检查错误的代码.

我理想的是一些狡猾的黑客,我可以使用它来自动记录这些方法创建的错误,而无需在每个方法调用上编写样板,从而为我提供了惰性NULL传递方法和错误的好处 - 记录样板.换句话说,我想写这个:

[managedObjectContext save:&magicAutologgingError];
Run Code Online (Sandbox Code Playgroud)

并且知道如果该方法创建了一个NSError,它会以某种方式神奇地记录下来.

我不太清楚如何解决这个问题.我考虑使用一个NSError记录自己的子类dealloc,但意识到由于我不负责实例化Cocoa方法创建的错误对象,所以无论如何都不会使用我的子类.我考虑过使用方法调配来让所有人 NSError自己登录dealloc,但我不确定这是否真的是可取的.我想过使用某种观察者类NSError来监视内存中给定的常量空间,我可以将其用于我想要记录的指针,但据我所知,没有办法像KVO那样做任何事情来观察内存中的任意空格,所以我看不到实现这个的方法,除了让一个线程反复检查错误以进行记录.

有谁能看到实现这个目标的方法?

jus*_*tin 1

只需创建一个包装函数(或类别方法)来执行您想要的操作:

bool MONSaveManagedObjectContext(NSManagedObjectContext * pContext) {
 NSError * error = nil;
 bool result = [pContext save:&error];
 if (!result && nil != error) {
  // handle  the error how you like -- may be different in debug/release
  NSLog(@"Error while saving: %@", error);
 }
 return result;
}
Run Code Online (Sandbox Code Playgroud)

并调用它。或者您可能更喜欢将错误处理分开:

void MONCheckError(NSError * pError, NSString * pMessage) {
 if (nil != pError) {
  // handle  the error how you like -- may be different in debug/release
  NSLog(@"%@: %@", pMessage, pError);
 }
}

...

NSError * outError = nil;
bool result = [managedObjectContext save:&outError];
MONCheckError(outError, @"Error while saving");
Run Code Online (Sandbox Code Playgroud)

始终留意重复的代码:)


我考虑过使用方法调配来让所有 NSError 都像这样在 dealloc 上记录自己,但我不确定这是否真的是可取的。

这是不可取的。