在我的应用程序中,我必须执行多部分 POST 请求。在请求中,我必须发送一个存储在设备照片库中的文件。上传完成并收到返回的数据后,我向请求发送了一条释放消息,但 Instruments 显示数据保留在设备的内存中。
这就是我创建请求对象的方式:
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
[request setHTTPShouldHandleCookies:YES];
[request setTimeoutInterval:30];
[request setHTTPMethod:@"POST"];
NSString *boundary = @"---------------------------14737809831466499882746641449";
// set Content-Type in HTTP header
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
[request setValue:contentType forHTTPHeaderField: @"Content-Type"];
// post body
NSMutableData *body = [[NSMutableData alloc] init];
// add parts (all parts are strings) `parts` is a NSDictionary object
for(id key in parts) {
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", key] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"%@\r\n", [parts objectForKey:key]] dataUsingEncoding:NSUTF8StringEncoding]];
}
// add files data - `file` is a ALAssetRepresentation object
NSData *fileData;
NSString *filename = [file filename];
Byte *buffer = (Byte*)malloc(file.size);
NSUInteger buffered = [file getBytes:buffer fromOffset:0.0 length:file.size error:nil];
fileData = [[NSData alloc] initWithBytesNoCopy:buffer length:buffered freeWhenDone:YES];
if (fileData) {
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
if ([requestType isEqualToString:PUBLISH_TYPE_VC_MANDA]) {
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"attachment\"; filename=\"%@\"\r\n", filename] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"Content-Type: image/jpeg\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
} else {
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"file\"; filename=\"%@\"\r\n", filename] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
}
[body appendData:fileData];
[body appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
}
[fileData release];
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
// setting the body of the post to the reqeust
[request setHTTPBody:body];
[body release];
// set the content-length
NSString *postLength = [NSString stringWithFormat:@"%d", [body length]];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setValue:@"Keep-Alive" forHTTPHeaderField:@"Connection"];
// set URL `adress` is a NSURL object
[request setURL:address];
//set cookie
if (storedCookie) {
NSDictionary *properties = [NSDictionary dictionaryWithObjectsAndKeys:[storedCookie name], NSHTTPCookieName, myDomain, NSHTTPCookieDomain,@"/",NSHTTPCookiePath, [storedCookie value], NSHTTPCookieValue, nil];
NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:properties];
NSArray* cookies = [NSArray arrayWithObjects: cookie, nil];
NSDictionary * headers = [NSHTTPCookie requestHeaderFieldsWithCookies:cookies];
[request setAllHTTPHeaderFields:headers];
}
在此之后,在我收到响应之后,我执行了[request release]
,但分配的字节保留在内存中。
我在分配模式下运行 Instruments
,它声称有一个类别为 Malloc 91MB
的对象(我上传的 ALAsset 的大小)。通过查看调用树,占用所有内存的 Symbol 是上述方法中的 [NSConcreteMutableData appendBytes:length:]
。
为什么不释放字节?更重要的是,为什么它必须将数据移动到设备的内存中?我见过像 Facebook 这样的应用程序从图库中上传非常大的视频而没有任何内存问题。
非常感谢您的关注,如有任何帮助或指示,我们将不胜感激
编辑: 进一步的调查表明,当我使用 [request release]
时,请求对象被释放,但它的主体没有。非常奇怪的行为......
EDIT2: 我明确使用了 [request.HTTPBody release];
并释放了字节。我仍然无法相信 [request release]
没有释放它的 body 。这可能是错误吗?
最佳答案
您的请求的 retainCount
为 2:
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; // 1
...
[request retain]; // 2
然后,如果您执行 [request release]
,它会减一。
解决方案是不执行[request retain]
。
关于ios - NSMutableRequest 对象主体的分配数据未被释放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16150516/