11

在 MacOS 上,我们有一个实现 ARC 的代理,它会根据用户的设置每 10 或 15 秒向服务器发出一些请求,并且工作了将近一年没有任何问题,而就在几周前,应用程序崩溃了在一台出现错误访问错误的计算机中,特别是在这一行:

[NSURLConnection sendSynchronousRequest:request returningResponse:&responseCode error:&error];

导致问题的机器的 Mac OS X 版本是 10.7.5,但是在具有相同操作系统版本的其他计算机上运行正常。

我们正在使用同步请求,因为这是我们需要做的工作,但是我们花了一些时间使调用异步但问题仍然存在。

因此,在查看其他帖子后,我们添加了一个缓存策略:[request setCachePolicy: NSURLRequestReloadIgnoringCacheData]; 以避免缓存请求出现任何问题。该应用程序确实运行得更好,但通常在 1500 - 1800 次迭代(30-40 分钟)之间仍然崩溃,然后在 15 或 20 次迭代之间崩溃。

通过查看堆栈溢出中的另一个问题,我们尝试使用 ASIHTTPRequest 解决此问题,但问题再次随机发生(它也可能在迭代 #2 或 #123x 中崩溃......)。

在错误出现之前,请求始终正常工作,我们正在获取数据并能够正常使用它。

启用 NSZombieEnabled 选项后,当应用程序崩溃时,我们不会收到任何消息,try/catch 块对我们也不起作用,因为错误指向上方的特定行;

[NSURLConnection sendSynchronousRequest:request returningResponse:&responseCode error:&error]

这是我们必须使用 NSURLConnection 发出请求的代码:

   NSMutableURLRequest *request = [[NSMutableURLRequest alloc]
   init]; [request setHTTPMethod:@"GET"]; [request setURL:[NSURL
   URLWithString:url]]; [request setTimeoutInterval: TIMEOUT];
   [request setCachePolicy: NSURLRequestReloadIgnoringCacheData];

    NSString *authenticationHeader = [NSString
    stringWithFormat:@"Basic %@", credentials]; [request
    addValue:authenticationHeader
    forHTTPHeaderField:@"Authorization"];

    NSError *error = nil; NSHTTPURLResponse *responseCode = nil;

    NSData *responseData = nil; responseData = [NSURLConnection
    sendSynchronousRequest:request returningResponse:&responseCode
    error:&error];

    if([responseCode statusCode] != 200){ *hasError =[NSString
    stringWithFormat: @"Error getting %@, HTTP status code %li",
    [responseCode statusCode]]; return @"";
    }
    }
    return [[NSString alloc] initWithData:responseData
    encoding:NSUTF8StringEncoding];

这是 ASIHttpRequest 的代码:

(NSString *)getDataFromURL: (NSString *)urlString withB64Credentials:(NSString *)credentials error:(NSString **)hasError
{
    NSString *response = @"";
    NSURL *url = [NSURL URLWithString:urlString];
    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
    [request setCachePolicy:ASIDoNotReadFromCacheCachePolicy];
    [request setTimeOutSeconds:TIMEOUT];

    NSString *authenticationHeader = [NSString stringWithFormat:@"Basic %@", credentials];
    [request addRequestHeader:@"Authorization" value:authenticationHeader];
    [request startSynchronous];

    NSError *error = [request error];
    if (!error)
        response = [request responseString];
    else
        NSLog(@"%@", [error description]);
    return response;
}

任何建议将不胜感激。

4

1 回答 1

1

首先,代码对我来说看起来不错。

我会用仪器做一个内存配置文件,以确保应用程序不会泄漏内存。由于此代码可能是您的应用程序中调用次数最多的代码,因此如果应用程序状态损坏,它也更有可能在此处崩溃。你也应该出于同样的原因测试你的硬件(http://osxdaily.com/2011/05/03/memtest-mac-ram-test/)。

此外,您的代码很容易隔离,因此您可以通过调用您的 URL 甚至一些公共 URL 来制作测试应用程序。如果你也可以让这个应用程序崩溃,那么你就有了向 Apple 提交错误的一切。

于 2013-09-15T08:44:01.290 回答