在Cocoa应用程序中使用异常处理与NSError [英] Using Exception Handling versus NSError in Cocoa Apps

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

问题描述

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



我来自Java,当需要处理错误时,异常是一种方法。不可否认,我仍然在Java的想法空间,但我慢慢来掌握所有的NSError提供。



我挂断的一件事是当发生错误时清理内存的任务。在许多情况下(例如使用C,C ++库,CoreFoundation等),你有很多内存清理,需要在由于错误而中断函数之前完成。



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

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

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

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

err = DoSomeStuffWithTheFileAndInfo(inFile,fileInfo);

if(err!= NoErr)
{
* error = [NSError errorWithDomain:@myDomaincode:100 userInfo:nil];
CloseFileHandle(inFile); //如果我们不这样做的话,会发生的事情
delete fileInfo;
return NO;
}

err = DoSomeOtherStuffWithTheFile(inFile,fileInfo);

if(err!= NoErr)
{
* error = [NSError errorWithDomain:@myDomaincode:101 userInfo:nil];
CloseFileHandle(inFile); //如果我们不这样做的话,会发生的事情
delete fileInfo;
return NO;
}

CloseFileHandle(inFile);
delete fileInfo;
return 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];
return NO;
}
@finally
{
CloseFileHandle(inFile); //如果我们不这样做的话,会发生的事情
delete fileInfo;
}
return YES;

我疯了,认为这是一个更优雅的解决方案,
我错过了什么?

解决方案

Daniel的回答是正确的,但这个问题应该得到一个更加钝的答案。 / p>

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





有一个在开发中心提供例外编程主题文档


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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆