user1333872
user1333872

Reputation:

Objective-C partially downloaded file and how can i clean memory

I have a problem.

My function must download extra large files piecemeal.

The function sends request to server to get part of a static file - for example bytes=50000000-100000000" in 50MB pieces.

The code concatenates all pieces in one file, so that it does overflow memory downloading.

But i have a problem - memory is not freed in each loop cycle, it just keeps adding up.

NSData *data;
NSOutputStream *stream;
NSString *savePath;
NSMutableURLRequest *request;
NSHTTPURLResponse *response;
int downloadingLimitBlock=50000000;//50MB
int downloadingFileFullSize=0;


int fIndex=0;//tmp

//
//

count=1;//count will changed if size more then minimum size

for (i = 0; i < count; i++)
{
    savePath=[NSString stringWithFormat:@"%@%@", videoContentFolderPath,[videoFilesNamesServerList objectAtIndex: fIndex]];//финдекс
    stream = [[NSOutputStream alloc] initToFileAtPath:savePath append:YES];
    [stream open];



    request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[videoFilesServerList objectAtIndex: fIndex]]];//финдекс
    [request setValue:@"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9) AppleWebKit/537.71 (KHTML, like Gecko) Version/7.0 Safari/537.71" forHTTPHeaderField:@"User-Agent"];
    [request setValue:[NSString stringWithFormat: @"bytes=%d-%d",(((i+1)*downloadingLimitBlock)-downloadingLimitBlock),(((i+1)*downloadingLimitBlock)-1)] forHTTPHeaderField:@"Range"];

    data = [NSURLConnection sendSynchronousRequest:request returningResponse: &response error: nil ];



    NSLog(@"bytes=%d-%d",(((i+1)*downloadingLimitBlock)-downloadingLimitBlock),(((i+1)*downloadingLimitBlock)-1));

        switch (response.statusCode) {
            case 206: {

                NSString *headerContentRange = [response.allHeaderFields valueForKey:@"Content-Range"];
                NSArray *tmpArray=[headerContentRange componentsSeparatedByString:@"/"];
                downloadingFileFullSize=[[tmpArray objectAtIndex:1] integerValue];


                //recalculate count
                count=ceil(downloadingFileFullSize/downloadingLimitBlock)+1;
                //recalculate count

                NSLog(@"Status code 206 OK");
                NSLog(@"sizefromserver %d",downloadingFileFullSize);

                break;
            }
            case 200: {
                downloadingFileFullSize = [[response.allHeaderFields valueForKey:@"Content-Length"] integerValue];
                NSLog(@"sizefromserver %d",downloadingFileFullSize);
                [self logIt:@"Warning! Maybe server is not supporting partly download static content, server returns status code 200, but must 206" ];
                ///Need add link to server too in logIt

                break;
            }
            default: {
                [self logIt:[NSString stringWithFormat:@"Error! while loading video content file,status code is %ld",(long)response.statusCode]];
                ///Need add link to server too in logIt

                break;
            }
        }



    NSUInteger left = [data length];
    NSLog(@"part %d lenght %lu",i,(unsigned long)left);
    NSUInteger nwr = 0;
    do {
        nwr = [stream write:[data bytes] maxLength:left];
        if (-1 == nwr) break;
        left -= nwr;
    } while (left > 0);
    if (left) {
        NSLog(@"stream error: %@", [stream streamError]);
    }


    [stream close];

    data=nil;
    stream=nil;

}



//////////////

LOG:

2013-12-29 00:18:38.890 RAT[151:60b] bytes=0-49999999
2013-12-29 00:18:38.892 RAT[151:60b] Status code 206 OK
2013-12-29 00:18:38.893 RAT[151:60b] sizefromserver 648943692
2013-12-29 00:18:38.894 RAT[151:60b] part 0 lenght 50000000
2013-12-29 00:19:07.624 RAT[151:60b] bytes=50000000-99999999
2013-12-29 00:19:07.626 RAT[151:60b] Status code 206 OK
2013-12-29 00:19:07.627 RAT[151:60b] sizefromserver 648943692
2013-12-29 00:19:07.628 RAT[151:60b] part 1 lenght 50000000
2013-12-29 00:19:52.253 RAT[151:60b] bytes=100000000-149999999
2013-12-29 00:19:52.255 RAT[151:60b] Status code 206 OK
2013-12-29 00:19:52.256 RAT[151:60b] sizefromserver 648943692
2013-12-29 00:19:52.257 RAT[151:60b] part 2 lenght 50000000
2013-12-29 00:20:18.133 RAT[151:60b] bytes=150000000-199999999
2013-12-29 00:20:18.134 RAT[151:60b] Status code 206 OK
2013-12-29 00:20:18.135 RAT[151:60b] sizefromserver 648943692
2013-12-29 00:20:18.136 RAT[151:60b] part 3 lenght 50000000
2013-12-29 00:20:40.666 RAT[151:60b] bytes=200000000-249999999
2013-12-29 00:20:40.667 RAT[151:60b] Status code 206 OK
2013-12-29 00:20:40.668 RAT[151:60b] sizefromserver 648943692
2013-12-29 00:20:40.669 RAT[151:60b] part 4 lenght 50000000
2013-12-29 00:21:04.930 RAT[151:60b] bytes=250000000-299999999
2013-12-29 00:21:04.931 RAT[151:60b] Status code 206 OK
2013-12-29 00:21:04.932 RAT[151:60b] sizefromserver 648943692
2013-12-29 00:21:04.933 RAT[151:60b] part 5 lenght 50000000
2013-12-29 00:21:26.906 RAT[151:60b] bytes=300000000-349999999
2013-12-29 00:21:26.907 RAT[151:60b] Status code 206 OK
2013-12-29 00:21:26.908 RAT[151:60b] sizefromserver 648943692
2013-12-29 00:21:26.909 RAT[151:60b] part 6 length 50000000

And out of memory

How can I clear memory when each iteration of the loop ends?

Upvotes: 1

Views: 509

Answers (1)

What you want to do is wrap the code inside the loop in an autorelease pool:

https://developer.apple.com/library/mac/documentation/cocoa/conceptual/memorymgmt/articles/mmAutoreleasePools.html

When execution exits the auto-release pool, memory that can be freed by ARC should be.

Basically it would look like:

for (i = 0; i < count; i++)
{
  @autoreleasepool
  {
    // All the code from the loop
  }
}

However you could use a lot less code, and not tie up a thread if you switch to downloading the whole file at once asynchronously using NSOutputStream as per the answer to this question:

Downloading a Large File - iPhone SDK

You still may want to stick with your mechanism as it lets the server operate with smaller chunks to send.

Upvotes: 2

Related Questions