Reputation: 6934
I have no issues downloading files under 250MBs, but when i am trying to download 250MB + zips the app just crashes unannounced with no error. Sometimes it goes through, sometimes it does not. Leaks confirm no bloat or memory loss.
ALSO i noticed now that the crash only happens when im debugging with xcode. When i run the app and download the larger files when im no debugging there are no issues
Do i need to approach AFNetworking classes differently when downloading a larger file?
here is my code
NSURL* url=[BFAppGlobals getServerURL:[M.Properties objectForKey:@"zip_path" ]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setTimeoutInterval:3600];
AFHTTPRequestOperation *operation = [[[AFHTTPRequestOperation alloc] initWithRequest:request] autorelease];
NSString* writePath=[BFAppGlobals getContentResourcePathForFile:strFile];
[delegate onStartDownload:M];
operation.outputStream = [NSOutputStream outputStreamToFileAtPath:writePath append:YES];
[operation setDownloadProgressBlock:^(NSInteger bytesRead, NSInteger totalBytesRead, NSInteger totalBytesExpectedToRead) {
int b=totalBytesRead ;
int total=totalBytesExpectedToRead;
float perc=(float)b/(float)total;
M.progress=perc;
[((NSObject*)delegate) performSelectorOnMainThread:@selector(onDataReceviedFromRequest:) withObject:M waitUntilDone:YES];
}];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSDictionary* params=[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:writePath,writeDirectory, M, nil] forKeys:[NSArray arrayWithObjects:@"Path",@"Dir",@"Model", nil]];
[self performSelectorInBackground:@selector(unzipDownloaded:) withObject:params];
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"fail! %@", [error localizedDescription]);
[delegate onErrorDownload:M WithError:[error localizedDescription]];
ActiveModel=nil;
}];
[operation start];
**************************** UPDATE ADDED CRASH LOG ***************************************
Thread 0 Crashed:
0 libobjc.A.dylib 0x37d24fbc objc_msgSend + 16
1 Foundation 0x35502508 __57-[NSNotificationCenter addObserver:selector:name:object:]_block_invoke_0 + 12
2 CoreFoundation 0x381aa570 ___CFXNotificationPost_block_invoke_0 + 64
3 CoreFoundation 0x381360c8 _CFXNotificationPost + 1400
4 Foundation 0x354763f4 -[NSNotificationCenter postNotificationName:object:userInfo:] + 60
5 Foundation 0x35477c24 -[NSNotificationCenter postNotificationName:object:] + 24
6 BFiPad 0x0006d2fc 0x1000 + 443132
7 CoreFoundation 0x3813d224 -[NSObject performSelector:withObject:] + 36
8 Foundation 0x35517750 __NSThreadPerformPerform + 344
9 CoreFoundation 0x381b2afc __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 8
10 CoreFoundation 0x381b22c8 __CFRunLoopDoSources0 + 208
11 CoreFoundation 0x381b106e __CFRunLoopRun + 646
12 CoreFoundation 0x381344d6 CFRunLoopRunSpecific + 294
13 CoreFoundation 0x3813439e CFRunLoopRunInMode + 98
14 GraphicsServices 0x37f0bfc6 GSEventRunModal + 150
15 UIKit 0x31cb473c UIApplicationMain + 1084
16 BFiPad 0x00003f72 0x1000 + 12146
17 BFiPad 0x00003f30 0x1000 + 12080
Upvotes: 3
Views: 2605
Reputation: 4657
I know that this question is old but the problem still seems to be relevant so I will post my solution anyway.
I have had the same problem where it would crash after downloading around 250MB and found out that it was caused by the fact that the download progress block was called every time a few bytes were downloaded which means that it gets called A LOT. Many times each second. So when the delegate method (which presumably does some stuff) gets called from here it can become quite memory intensive.
My solution was to track the download progress and only call the delegate method if the change is significant (I decided on more than 1%):
[operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
float progress = ((float)totalBytesRead) / totalBytesExpectedToRead;
if ((progress - totalProgress) > 0.01) {
totalProgress = progress;
[delegate updateProgress:progress];
}
}];
float totalProgress
is an instance variable.
This fix reduced the memory usage from around 280MB at the point of the crash to around 30MB which my app was using already. I.e. there was no noticeable memory rise during the download process (assuming your are downloading directly to a file, not to the memory).
Upvotes: 1
Reputation: 6934
It seems that this is only happenning in debug mode. Running out of debug mode or on release more solves this problem
Upvotes: 2
Reputation: 19544
It doesn't look like operation
is owned by anything in particular, so there's no guarantee that it will stick around in memory. Try using an NSOperationQueue
(perhaps one attached to an AFHTTPClient
, which would clean up a lot of that code), or setting this as a retained property in the controller initiating the upload.
Upvotes: 1