2016-07-23 3 views
0

Используйте этот код для загрузки файла на моем устройстве. Но на 99% загрузки интерфейса останавливается (я не могу нажать на кнопку). Через 20 секунд все работает нормально и загрузка = 100%. Почему интерфейс останавливается при загрузке 99%? Как это исправить?Загрузить файл на устройстве - это интерфейс блокировки

- (void)viewDidLoad 
{ 
dispatch_async(dispatch_get_main_queue(), ^{ 

    _session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]]; 
     }); 

    [self.progressView setProgress:0 animated:NO]; 
} 

- (IBAction)btnClicked:(id)sender { 
    if(_downloadTask == nil){ 

     _url =[NSURL URLWithString:@"https://www.nsw.gov.au/sites/default/files/bg-view-nsw-media.png"]; 

     _downloadTask = [_session downloadTaskWithURL:_url1]; 

     [_downloadTask resume]; 

    } 

    else 

    [_downloadTask resume]; 
} 

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location 
{ 
    dispatch_async(dispatch_get_main_queue(), ^{ 


    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [paths objectAtIndex:0]; 
    NSString *filePath = [documentsDirectory stringByAppendingPathComponent:@"image1.mp3"]; 
    BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:filePath isDirectory:NO]; 


    NSData *urlData = [NSData dataWithContentsOfURL:_url]; 
    [urlData writeToFile:filePath atomically:YES]; 
} 

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite; 
{ 
dispatch_async(dispatch_get_main_queue(), ^{ 
    [ _progressView setProgress:totalBytesWritten/totalBytesExpectedToWrite animated:YES]; 

    NSString *percentage = [NSString stringWithFormat:@"%d%%", (int)((totalBytesWritten/totalBytesExpectedToWrite)*100)]; 
    [_label setText:[NSString stringWithFormat:@"%@%%", percentage]]; 

    NSLog(@"%lld", totalBytesWritten); 

    _label = [[UILabel alloc]initWithFrame:CGRectMake(91, 15, 500, 50)]; 
    [_label setText: percentage]; 
    _label.numberOfLines = 1; 
    _label.backgroundColor = [UIColor blackColor]; 
    _label.textColor = [UIColor whiteColor]; 
    _label.textAlignment = NSTextAlignmentCenter; 
    [self.view addSubview:_label]; 


    }); 

UPD

Тогда я удалить этот код

NSData *urlData = [NSData dataWithContentsOfURL:_url]; 
    [urlData writeToFile:filePath atomically:YES]; 

все работает отлично

ответ

0

Вы не должен поставить все в main thread. Единственное, что нужно сохранить в main thread, - UI updates.

Действительно, каждое действие, выполненное в main thread, блокирует интерфейс до тех пор, пока действие не завершится. Вы хотите, чтобы ваша загрузка выполнялась в background, и только UI updates в main thread.

То, что вы должны сделать после этого кода:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
    //Do background work 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     //Update UI 
    }); 
}); 

В вашем случае код должен выглядеть так:

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location 
{ 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
     NSString *documentsDirectory = [paths objectAtIndex:0]; 
     NSString *filePath = [documentsDirectory stringByAppendingPathComponent:@"image1.mp3"]; 
     BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:filePath isDirectory:NO]; 


     NSData *urlData = [NSData dataWithContentsOfURL:_url]; 
     [urlData writeToFile:filePath atomically:YES]; 
    }); 
} 
+0

не работает. Как это выглядит в коде? – user214155

+0

Я думаю, что эта строка [urlData writeToFile: filePath atomically: YES]; (и, возможно, выше) должны быть вызваны в фоновом режиме. – AnthoPak

+0

Я обновляю свой вопрос. Пожалуйста, проверьте – user214155

0

код внутри вашего

dispatch_async(dispatch_get_main_queue(), ^{ /* code */ }); 

будет выполняться на основном потоке. В большинстве случаев вам следует избегать выполнения длинных процессов там, потому что ui (ваша кнопка) не может ответить до завершения вашей задачи.

Так что попробуйте использовать что-то вроде этого для фоновых загрузок

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ /* background download*/ }); 

и использовать свое решение после того, как загрузка завершена, чтобы обновить пользовательский интерфейс на основном потоке.

Смежные вопросы