【问题标题】:Problem passing NSError back as a return parameter将 NSError 作为返回参数传回的问题
【发布时间】:2010-12-03 04:03:51
【问题描述】:

我在传回 NSError 对象时遇到问题。访问对象的第一行代码(在本例中,我插入了一个 NSLog)导致“EXC_BAD_ACCESS”。

这是因为我没有显式创建一个 NSError 对象,而是从 NSURLRequest 中获取一个并将其传回吗?在这个特定的函数 (downloadFile:) 中,我想从其他函数中检索一些错误,但我在函数中的另外两个场合创建了 NSError。

感谢任何帮助。

这是有问题的代码:

-(void)someCode {
NSError *err = nil;

localPool = [[NSAutoreleasePool alloc] init];

if (!iap) {
    iap = [[InAppPurchaseController alloc] init];
}

if (![self.iap downloadFile:@"XXXXX.plist" withRemoteDirectory:nil withLocalDelete:YES withContentType:@"text/xml" Error:&err] ) {
    //"EXC_BAD_ACCESS" on calling NSLog on the next line? 
    NSLog(@"Error downloading Plist: %@", [err localizedDescription]);

    [self performSelectorOnMainThread:@selector(fetchPlistFailed:) withObject:err waitUntilDone:NO];
    [localPool drain], localPool = nil;
    return NO;
}
//Removed the remainder of the code for clarity.

[localPool drain], localPool = nil;
return YES;
}


-(BOOL)downloadFile:(NSString *)fileName
withRemoteDirectory:(NSString *)remoteDirectory
 withLocalDelete:(BOOL)withLocalDelete
 withContentType:(NSString *)contentTypeCheckString
     Error:(NSError **)error {

UIApplication *app = [UIApplication sharedApplication];
app.networkActivityIndicatorVisible = YES; 

NSError *localError = nil;

NSAutoreleasePool *localPool = [[NSAutoreleasePool alloc] init];

NSString *urlString = [NSString stringWithFormat:@"http://XXXXX/%@", fileName];

NSLog(@"Downloading file: %@", urlString);

NSURL *url = [NSURL URLWithString:urlString];

NSURLRequest *req = [[NSURLRequest alloc] initWithURL:url];

NSHTTPURLResponse *response = nil;

NSData *responseData = [NSURLConnection sendSynchronousRequest:req returningResponse:&response error:&localError];

[req release];

if (response == nil || localError) {
    NSLog(@"Error retrieving file:%@", [localError localizedDescription]);
    if (error != NULL) {
        *error = localError;
        //THIS NSLog call works just fine.
        NSLog(@"Error copied is:%@", [*error localizedDescription]);
    }
 [localPool drain], localPool = nil;
 app.networkActivityIndicatorVisible = NO; 
 return NO;
}

//Rest of function omitted for simplicity.
}

【问题讨论】:

  • 对与问题无关的代码的一个观察:检查 sendSynchronousRequest: 是否因错误而失败的方法是检查其返回值为 nil,not 响应范围。如果 responseData 为 nil,localError 指向的错误将是一个有效的错误信息,否则你应该忽略它。因此,您对 localError 的检查以查看它是否为 nil 是没有意义的,并且您对响应的检查是不正确的。实际上,您不妨将错误传递为 NSError** 并保存复制。
  • 优秀的捕捉和评论!我会根据您的建议进行更改。

标签: iphone objective-c nserror


【解决方案1】:

我猜你的NSError 对象是autoreleased 并穿上你的localPool。你耗尽了localPool,从而破坏了NSError

你真的需要localPool 吗?如果没有,只需删除localPools。

另外,您似乎忘记在someCode 中排空localPool。希望你只是没有复制它......

-(void)someCode {
    NSError *err = nil;

    localPool = [[NSAutoreleasePool alloc] init];

    if (!iap) {
        iap = [[InAppPurchaseController alloc] init];
    }

    if (![self.iap downloadFile:@"XXXXX.plist" withRemoteDirectory:nil withLocalDelete:YES withContentType:@"text/xml" Error:&err] ) {
             ....
            [localPool drain], localPool = nil;
            return NO;
    }
    [localPool drain], localPool = nil; // missing
}

【讨论】:

  • 很好的答案,但我只想说,如果您创建一个自动释放池并忘记将其排空,这没关系,因为当父池被排空时,它也会自动排空其所有幸存的子池.
  • 谢谢杰里米,我不知道。
  • 啊!就是这样!你是对的,我没有复制所有的代码。我已经编辑了我的问题以反映这一点。我在代码的其他地方耗尽了池。我再看一遍代码,但是在这个方法中释放删除本地池应该是没有问题的。我仍然习惯于 Objective-C 中的内存管理。
猜你喜欢
  • 2012-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-24
  • 1970-01-01
  • 2023-03-17
  • 2018-04-09
相关资源
最近更新 更多