我正在使用RestKit在我的应用程序中下载多个文件。只要文件不是太大,一切都像魅力一样。不幸的是,我尝试下载一个大视频文件(大约230 MB)并获得memory warning
并且应用程序崩溃。
我使用以下行开始下载
[[RKClient sharedClient] get:[NSString stringWithFormat:@"/%@", listItem.filename] delegate:self];
在委托方法中,我将其保存在appDirectory/Library/Caches/
- (void)request:(RKRequest *)request didLoadResponse:(RKResponse *)response
{
NSURL * url = [NSURL fileURLWithPath:[cacheDirectory stringByAppendingPathComponent:response.URL.lastPathComponent]];
[[response body] writeToURL:url atomically:YES];
}
我已经检查了仪器中的应用程序是否存在内存泄漏,并看到Live Bytes
的{{1}}在*Overall Allocations*
到达Low Memory Alerts
之前不断上升。但是没有泄漏。
删除负责保存文件的行(100 MB
)没有改变任何内容,所以我猜问题是在RestKit中的某个地方。
虽然研究我偶然发现method of ASIHTTPRequest
允许直接下载文件并认为这样可以解决问题,但不确定。
RestKit中是否存在我错过的直接下载的可能性?
或
有更好的方法可以下载我应该知道的RestKit文件吗?
答案 0 :(得分:4)
我遇到了同样的问题,遗憾的是我认为除了修改本地RestKit副本之外还有其他办法。问题位于- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
,完全位于[_body appendData:data];
。如您所见,RestKit将响应的主体保留在内存中,并在从服务器发送时附加字节。这就是你得到低内存警告的原因。我的解决方案是向RKRequest添加一个属性并将数据直接写入文件系统,具体取决于请求是否是一个大文件请求:
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
if ([_request dontKeepBytesInMemory]) {
if ([[_request delegate] respondsToSelector:@selector(request:didReceivedData:totalBytesExectedToReceive:)]) {
[[_request delegate] request:_request didReceivedData:data totalBytesExectedToReceive:_httpURLResponse.expectedContentLength];
}
} else {
[_body appendData:data];
if ([[_request delegate] respondsToSelector:@selector(request:didReceivedData:totalBytesReceived:totalBytesExectedToReceive:)]) {
[[_request delegate] request:_request didReceivedData:[data length] totalBytesReceived:[_body length] totalBytesExectedToReceive:_httpURLResponse.expectedContentLength];
}
}
}
我还需要在协议中使用额外的RKRequest委托方法,因此我可以单独处理大响应。原始委托方法定义totalBytesReceived
,它只是[_body length]
,但如果直接将字节写入文件系统,则只需检查当前文件大小即可跟踪下载状态。如果您正在寻找一种直接将字节保存到文件系统的好方法,请查看NSFileHandle类 - 它支持文件偏移,因此您只需向其中抛出任何NSData,它就会自动为您附加。