当从NSMutableArray下载时,“for”循环崩溃

8

我的NSMutableArray里有4个元素。我有一个很棒的代码用于下载文件和将文件数据显示在UITextView中以进行测试。没有for循环,一切都正常。给我问题的代码在这个函数中:

- (void)complexDownload {
    int i;
    for (i=0; i < downloadArray.count; i++) {
        if (isBusy == NO) {
            [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
            downloadURL = [downloadArray objectAtIndex:i];
            NSLog(@"URL is %@", downloadURL);
            NSLog(@"Downloading object at index %i", i);
            NSURL *url = downloadURL;
            NSURLRequest *theRequest=[NSURLRequest requestWithURL:url
                                                      cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                  timeoutInterval:60.0];

            NSURLConnection *theConnection = [NSURLConnection connectionWithRequest:theRequest delegate:self];

                if (theConnection) {
                    self.downloadData = [NSMutableData data];
                    isBusy = YES;
                    NSLog(@"Busy value in download cycle equals %i, downloading", isBusy);
                } else {
                    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
                    NSLog(@"Connection failed");
                    isBusy = NO;
                }
        }
    }
}

我最开始认为问题可能出在 isBusyBOOL 上,但即使没有 if 条件,应用程序仍会崩溃。编译器没有给我任何错误信息,只有这个:

这是大截屏的链接.

其余的函数如下:

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    [downloadData appendData:data];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    NSString *dataString = [[NSString alloc] initWithData:downloadData encoding:NSASCIIStringEncoding];
    self.dataTextView.text = dataString;
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
    NSLog(@"Download finished!");
    isBusy = NO;
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    NSLog(@"%@", error);
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
}

所有的NSLog值都非常好,数组已经有了链接,所有链接都是正确的。


4
你应该真正使用NSOperation类,而不是像这样操作。 - Pierre
@Pierre 我知道,我已经尝试过了,问题在于NSOperationQueue有一些限制,我无法重新排序操作,并且无法充分管理它们。 - Sergey Grischyov
4
或者代码块。不管怎样,你有完整的崩溃日志或输出吗?通常这可以指向潜在问题。你也可以从异常中添加断点。进入断点选项卡并添加一个新的异常断点。它将在导致崩溃的行上停止,以便你可以找出原因。 - Bill Burgess
@BillBurgess 我已经编辑了帖子,并附上了崩溃输出的截图。 - Sergey Grischyov
你设置了异常断点吗?我猜是的。有时候点击“继续”一两次是个好主意。在调试控制台上显示实际错误信息之前,可能需要点击几次“继续”。然而,请查看调用堆栈。异常抛出在SGDownloader complexDownl...的某个地方。点击它,你应该能看到代码中哪一行抛出了异常。请提供这些额外的信息给我们。 - Hermann Klecker
没读完整个线程,但这会导致一个范围异常,因为你的for循环从0到array.count迭代,并且访问array[arrat.count]超出了边界。应该是array.count-1。 - Mario
4个回答

6

我的猜测是,在某个时刻,downloadArray[i] 可能已经损坏,或者它不是一个NSUrl。代码在 [NSURLRequest requestWithURL...] 中调用的 CFURLCopyAbsoluteURL() 处崩溃。


你是对的! 传递给实例变量的URL是NSSstring类型的,我没有注意到它,因为它直接从NSArray中获取。 - Sergey Grischyov

1

我认为这是与[url-object]有关的问题,即[NSURLRequest requestWithURL:url]。没有必要将URL复制到另一个对象中。请尝试以下方法:

NSLog(@"URL is %@", [downloadArray objectAtIndex:i]);
NSLog(@"Downloading object at index %i", i);
NSURL *url = [downloadArray objectAtIndex:i];

(或在 downloadURL 前添加 self.)

如果您的 downloadArray 包含 NSStrings:

NSURL *url = [NSURL URLWithString:[downloadArray objectAtIndex:i]];

我建议使用外部框架,例如[ASIHTTPRequest](http://allseeing-i.com/ASIHTTPRequest/)。

1
ASIHTTPRequest很棒,但它已经很长时间没有得到支持了。我被告知https://github.com/AFNetworking/AFNetworking是现在使用的好选择。 - Darren
是的,没错,ASIHTTPRequest 的最后一次提交已经是5个月前了!感谢提供这个替代方案,我会在当前项目中进行测试。 - flexo

1
你使用异步API initWithRequest:delegate:,并尝试通过使用isBusy标志使其同步。这种方法本来就是非常错误的,NSURLConnection类已经足够智能了,如果你正确使用它,就不需要使用任意的标志。 你应该认真考虑使用NSOperations或GCD。如果你计划进行更复杂的连接编程,也许你应该考虑使用第三方框架,比如RestKit。

NSOperations有很多限制,虽然这种方法非常复杂,但实际上确实提供了一些关于下载内容和时间的选项。 - Sergey Grischyov
我认为这并不复杂,只是误用了 NSURLConnection API,这将会给维护或更新此代码的人带来困惑。Hermann 的答案解决了 API 的误用问题,所以我很高兴你喜欢它。 - lawicko

1
摆脱for循环和isBusy指示器。 在complexDownload中,始终仅处理第一个或最后一个(适合哪个就用哪个)对象,然后将其从数组中删除。在connectionDidFinish中再次调用complexDownload。为此使用performSelector。等待时间甚至可以是0.0f。这样做,您的downloadArray将充当某种队列。

非常感谢您的宝贵建议!这是一个很棒的想法! - Sergey Grischyov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接