objective-c - 可能是 NSURLSession 或 NSMutableURLRequest 没有通过循环释放内存调用

标签 objective-c nsurlconnection nsurlsession nsurl nsmutableurlrequest

我的问题:- NSURLSession 不会释放先前调用的 5MB block 的 API 内存

我在 do while 循环中调用 API 来上传 500MB 视频。我必须使用不同的 API(而不是在一个 API 中)发送每 5MB block 。

例如,500MB 视频并创建 100 个 block 并使用 NSURLSession 发送,因此调用 100 次,但 NSURLSession 不会释放先前调用的 5MB block 的 API 内存

(1) 我创建了 5MB block 。

(2) 使用 NSFileHandle 读取文件并使用 OffSet 读取 5MB block

(3) 更改所有 block 的 URL 并调用 api(需要在不同的 URL 发送所有 block )

我不想在 NSData 中转换视频(500MB),我想通过 API 发送 block

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
        //dispatch_group_t group = dispatch_group_create();

        __block NSUInteger counterFailure = 0; // PSM Anks calling blob by url fails 4 time, exit for funtion

        arrBlobIds = [[NSMutableArray alloc]init];

        __block NSInteger intBlockIdCount = 100000; // PSM Anks blobid to assign id to every blob
        __block NSUInteger offset = 0; // PSM Anks offset to start posution to read data

        NSUInteger length = [[[NSFileManager defaultManager] attributesOfItemAtPath:[urlOfGallaryVideo path] error:nil] fileSize]; // PSM anks total lenght of media
        NSUInteger intChunkSize = (5000 * 1024); // PSM anks chunk size

            while (offset < length){

                //dispatch_group_enter(group);

                NSLog(@"offset 1 : %lu",(unsigned long)offset);

                // PSM Anks Creat Chunk from file according to length

                NSUInteger intThisChunkSize = length - offset > intChunkSize ? intChunkSize : length - offset;
                //NSData* chunk = [NSData dataWithBytesNoCopy:(char *)[myBlob bytes] + offset length:intThisChunkSize freeWhenDone:NO];

                __block NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingAtPath:[urlOfGallaryVideo path]];
                [fileHandle seekToFileOffset:offset];
                __block NSData *dataChunk = [fileHandle readDataOfLength:intThisChunkSize];

                // PSM Anks Convert block id in Base 64 encode

                NSData *dataBlockId = [[NSString stringWithFormat:@"%ld",intBlockIdCount] dataUsingEncoding:NSUTF8StringEncoding];
                NSString *base64BlockId = [dataBlockId base64EncodedStringWithOptions:0];

                NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@&comp=block&blockid=%@",[dictAzureSAS objectForKey:@"uri"],base64BlockId]]];

                [request setHTTPMethod:@"PUT"];
                [request setHTTPBody:dataChunk];
                //[request setValue:[NSString stringWithFormat:@"%lu",(unsigned long)dataChunk.length] forHTTPHeaderField:@"Content-Length"]; // Do not need
                //[request setValue:strVideoMIMEType forHTTPHeaderField:@"Content-Type"]; // Do not need
                [request addValue:@"BlockBlob" forHTTPHeaderField:@"x-ms-blob-type"];

                //NSLog(@"request : %@",request);
                //NSLog(@"dataChunk.length : %lu \n url for blob %@ \n request %@",(unsigned long)dataChunk.length,[NSURL URLWithString:[NSString stringWithFormat:@"%@&comp=block&blockid=%@",[dictAzureSAS objectForKey:@"uri"],base64BlockId]],request);

                NSLog(@"dataChunk.length : %lu",(unsigned long)dataChunk.length);

                NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
                config.URLCache = [[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:nil];
                config.timeoutIntervalForRequest = 20.0;
                config.URLCredentialStorage = nil;
                config.requestCachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
                ///NSURLSession *session = [NSURLSession sessionWithConfiguration:config];
                config = nil;

                //NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
                NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];


                NSURLSessionDataTask *dataTaskForUpload = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {


                    NSLog(@"Finished with status code: %li", (long)[(NSHTTPURLResponse *)response statusCode]);
                    NSLog(@"response: %@", response);
                    NSLog(@"error: %@ %@", error,error.description);

                    if(data != nil) // PSM anks Check Data is nil otherwise app crashed
                    {
                        NSMutableArray *jsonList = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
                        NSLog(@"jsonList: %@", jsonList);
                    }

                    dataChunk = nil;
                    fileHandle = nil;
                    if(error == nil)
                    {
                        /*
                        // PSM Anks First Add Then increment
                        [arrBlobIds addObject:base64BlockId];
                        intBlockIdCount++;
                        offset += intThisChunkSize;

                        counterFailure = 0;
                        */

                    }
                    else
                    {
                        /*
                        counterFailure++;
                        offset = intThisChunkSize;

                        if(counterFailure >= 4)
                        {

                            NSLog(@"Enter counter Failure %lu",(unsigned long)counterFailure);
                            counterFailure = 0;
                            [self stopLoader];
                            [CommonAlertViewMsgs cannotConnectServer:self];
                            return ;
                        }
                        */
                    }
                    //dispatch_group_leave(group);
                    dispatch_semaphore_signal(semaphore);
                    [session finishTasksAndInvalidate];

                }];


                [dataTaskForUpload resume];
                dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);


                NSLog(@"offset 2 : %lu",(unsigned long)offset);
            }

最佳答案

您的问题可能是您的NSData对象被放入自动释放池中,直到您的 main dispatch_async 之后它才会被耗尽。 block 完成。您可以通过添加 @autoreleasepool 来解决眼前的问题。到你的 while 循环;即

while (offset < length) @autoreleasepool {

但是,您的dispatch_semaphore_wait最后会阻塞调度队列,这通常是不鼓励的。我建议除了添加 @autoreleaspool 之外,到 while 循环,使用调度组而不是信号量,并使用 dispatch_group_notify最后而不是 dispatch_group_wait 。这将导致您的主要 dispatch_async block 完成,这将释放其中积累的所有自动释放的对象,然后是您传递给 dispatch_group_notify 的 block 所有操作完成后将被调用。

编辑:更多地了解您想要做什么,这里有一种替代方案,它将一次运行一个进程,同时仍然不会阻塞调度队列:

(伪代码)

- (void)sendRequestWithOffset:length:otherParameters: {
    send the url request {
        do what you do

        if newOffset < length {
            [self sendRequestWithOffset:newOffset length:length otherParameters:whatever];
        } else {
            hooray, we're done
        }
    }
}

这有点像递归调用(但不是真的,因为我们不会累积堆栈帧)。基本上它是 while 循环的异步版本;您的任务一次只发生一个,不会阻塞调度队列,并且由于每个调度队列都有自己的自动释放池,因此您也不会积累自动释放的对象,并且您的内存使用量应该保持合理。

关于objective-c - 可能是 NSURLSession 或 NSMutableURLRequest 没有通过循环释放内存调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47078719/

相关文章:

ios - 出现键盘时缩小 UIWebView

iphone - UIView 未正确释放

NSURLConnection 方法在 IOS5 中不再可用

ios - Swift 2 JSON POST 请求 [NSMutableURLRequest 的 HTTPBody 的字典与字符串]

objective-c - 如何在后台线程上执行长时间操作,然后在主线程上更新 UI

iphone - 将视频添加到应用程序

ios - NSURLConnection 和 sendAsynchronousRequest :queue:completionHandler: - does the completion block run in the main thread

ios - 如何在 IOS 中检查所有 NSURLConnections 的 SSL 证书

ios - URLSession didReceiveChallenge 太慢

ios - NSURLSession 完成处理程序非常慢