在Cocoa应用程序中使用异常处理与NSError

在Cocoa应用程序中使用异常处理与NSError

本文介绍了在Cocoa应用程序中使用异常处理与NSError的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

嗯所有的我一直在阅读Apple对何时/何处/如何使用NSError与@ try / @ catch / @ finally的建议。基本上,我的印象是,苹果认为最好避免使用异常处理语言构造,除非是在意外的错误情况下停止程序执行的机制(也许有人可以给出一个这样的情况的例子)。



我来自Java,当有人想要处理错误时,异常是出路。诚然,我仍然在Java的想法空间,但我慢慢来抓住NSError提供的所有内容。



我挂断的一件事是发生错误时清理内存的任务。在许多情况下(例如使用C,C ++库,CoreFoundation等),您有很多内存清理需要在由于错误导致功能崩溃之前完成。



这是一个准确地反映我遇到的情况的一个例子。使用一些虚数据结构,该函数打开一个文件句柄并创建一个'MyFileRefInfo'对象,其中包含有关该文件的操作的信息。在文件句柄关闭之前,有些东西是用文件完成的,结构体的内存被释放。使用Apple的建议我有这个方法:

   - (BOOL)doSomeThingsWithFile:(NSURL *)filePath错误:(NSError **)错误
{
MyFileReference inFile; //让我们说这是一个CF结构,打开一个文件引用
MyFileRefInfo * fileInfo = new MyFileRefInfo(...一些init参数...);

OSStatus err = OpenFileReference((CFURLRef)filePath,& inFile);

if(err!= NoErr)
{
* error = [NSError errorWithDomain:@myDomaincode:99 userInfo:nil];
删除fileInfo;
返回NO;
}

err = DoSomeStuffWithTheFileAndInfo(inFile,fileInfo);

if(err!= NoErr)
{
* error = [NSError errorWithDomain:@myDomaincode:100 userInfo:nil];
CloseFileHandle(inFile); //如果我们不这样做坏事情发生
删除fileInfo;
返回NO;
}

err = DoSomeOtherStuffWithTheFile(inFile,fileInfo);

if(err!= NoErr)
{
* error = [NSError errorWithDomain:@myDomaincode:101 userInfo:nil];
CloseFileHandle(inFile); //如果我们不这样做坏事情发生
删除fileInfo;
返回NO;
}

CloseFileHandle(inFile);
删除fileInfo;
返回YES;

}

现在我的Java逻辑告诉我,最好将它设置为try / catch / finally结构,并将所有调用关闭文件句柄并在finally块中释放内存。



喜欢这样..

  ... 

@try
{
OSStatus err = OpenFileReference((CFURLRef)filePath,& inFile);
if(err!= NoErr)
{
...抛出一些异常,并附有错误代码和描述...
}

err = DoSomeStuffWithTheFileAndInfo(infile中,的fileInfo);

if(err!= NoErr)
{
...抛出一些异常...
}

...等...
}
@catch(MyException * ex)
{
* error = [NSError errorWithDomain:@myDomaincode:[ex errorCode] userInfo:nil]
返回NO;
}
@finally
{
CloseFileHandle(inFile); //如果我们不这样做坏事情发生
删除fileInfo;
}
return YES;

我觉得这是一个更加优雅的解决方案,而冗余代码更少,我很疯狂?
我错过了什么吗?

解决方案

丹尼尔的答案是正确的,但是这个问题值得一个比较平常的答案。 / p>

只有在遇到不可恢复的错误时才抛出异常。



在传达可能的错误条件时使用NSError



通过Apple框架中的框架抛出的任何异常都可能导致未定义的行为。



有一个可在开发中心使用。


Hey all. I've been reading up on Apple's suggestions for when/where/how to use NSError versus @try/@catch/@finally. Essentially, my impression is that Apple thinks it best to avoid the use of exception handling language constructs except as a mechanism for halting program execution in unexpected error situations (maybe someone could give an example of such a situation?)

I come from Java, where exceptions are the way to go when one wants to handle errors. Admittedly, I'm still in the Java thoughtspace, but I'm slowly coming to grips with all that NSError has to offer.

One thing I'm hung up on is the task of cleaning up memory when an error occurs. In many situations (e.g. using C, C++ libraries, CoreFoundation, etc..) you have a lot of memory cleanup that needs to be done before breaking out of a function due to an error.

Here's an example I cooked up that accurately reflects the situations I've been encountering. Using some imaginary data structures, the function opens up a file handle and creates a 'MyFileRefInfo' object which contains information about what to do with the file. Some stuff is done with the file before the file handle is closed and the memory for the struct freed. Using Apple's suggestions I have this method:

- (BOOL)doSomeThingsWithFile:(NSURL *)filePath error:(NSError **)error
{
  MyFileReference inFile; // Lets say this is a CF struct that opens a file reference
  MyFileRefInfo *fileInfo = new MyFileRefInfo(...some init parameters...);

  OSStatus err = OpenFileReference((CFURLRef)filePath ,&inFile);

  if(err != NoErr)
  {
    *error = [NSError errorWithDomain:@"myDomain" code:99 userInfo:nil];
    delete fileInfo;
    return NO;
  }

  err = DoSomeStuffWithTheFileAndInfo(inFile,fileInfo);

  if(err != NoErr)
  {
    *error = [NSError errorWithDomain:@"myDomain" code:100 userInfo:nil];
    CloseFileHandle(inFile); // if we don't do this bad things happen
    delete fileInfo;
    return NO;
  }

  err = DoSomeOtherStuffWithTheFile(inFile,fileInfo);

  if(err != NoErr)
  {
    *error = [NSError errorWithDomain:@"myDomain" code:101 userInfo:nil];
    CloseFileHandle(inFile); // if we don't do this bad things happen
    delete fileInfo;
    return NO;
  }

  CloseFileHandle(inFile);
  delete fileInfo;
  return YES;

}

Now.. my Java logic tells me that it would be better to set this up as a try/catch/finally structure and put all the calls to close the file handle and free memory in the finally block.

Like so..

    ...

    @try
    {
      OSStatus err = OpenFileReference((CFURLRef)filePath ,&inFile);
      if(err != NoErr)
      {
        ... throw some exception complete with error code and description ...
      }

      err = DoSomeStuffWithTheFileAndInfo(inFile,fileInfo);

      if(err != NoErr)
      {
         ... throw some exception ...
      }

      ... etc ...
}
@catch(MyException *ex)
{
        *error = [NSError errorWithDomain:@"myDomain" code:[ex errorCode] userInfo:nil];
        return NO;
}
@finally
{
        CloseFileHandle(inFile); // if we don't do this bad things happen
        delete fileInfo;
}
return YES;

Am I crazy in thinking that this is a much more elegant solution with less redundant code?Did I miss something?

解决方案

Daniel's answer is correct, but this question deserves a rather more blunt answer.

Throw an exception only when a non-recoverable error is encountered.

Use NSError when communicating error conditions that may be recovered from.

Any exception that is thrown through a frame in Apple's frameworks may result in undefined behavior.

There is an Exceptions programming topic document available in the dev center.

这篇关于在Cocoa应用程序中使用异常处理与NSError的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-20 14:58