Objective-C:GUI褪色

用户

我想下载压缩文件并将其解压缩。当我下载zip时,一切正常。但是,解压缩后,我的界面会停止几秒钟,有时应用程序会崩溃。如何解决?

压缩文件大小650 MB

downloadButton-单击按钮时激活下载

 -(IBAction) downloadButton:(id)sender{

_url1 =[NSURL URLWithString:@"link"];

_downloadTask1 = [_session downloadTaskWithURL:_url1];

[_downloadTask1 resume];
}

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{

if (downloadTask == _downloadTask1) {

    _paths1 = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    _documentsDirectory1 = [_paths1 objectAtIndex:0];
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSURL *newLocation = [NSURL URLWithString:[NSString stringWithFormat:@"file://%@/1.zip", _documentsDirectory1]];
    NSError *error;
    [fileManager copyItemAtURL:location toURL:newLocation error:&error];
}
}

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten  totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite;{

if( downloadTask == _downloadTask1){
    _progress1 = [[NSNumber numberWithInteger:totalBytesWritten] floatValue];_total1 = [[NSNumber numberWithInteger:totalBytesExpectedToWrite] floatValue];
    _percentage = [NSString stringWithFormat:@"%.f%%", ((_progress1 / _total1) * 100)];
    (NSLog (_percentage, @"%.f%%"));
    _label.text = _percentage;
}
if ([_percentage isEqual: @"100%"]) {
    _label.text = @«ok»;
    [self performSelector:@selector(zip) withObject:nil afterDelay:0.1];
    [self performSelector:@selector(removeZip) withObject:nil afterDelay:5.0];
}
}

-(void) zip{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    _paths1 = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    _documentsDirectory1 = [_paths1 objectAtIndex:0];
    _zipPath1 = [_documentsDirectory1 stringByAppendingPathComponent:@"1.zip"];
    _destinationPath1 = [NSString stringWithFormat:@"%@",_documentsDirectory1];
    [SSZipArchive unzipFileAtPath:_zipPath1 toDestination:_destinationPath1];
});
}

-(void) removeZip{
_paths1 = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
_documentsDirectory1 = [_paths1 objectAtIndex:0];
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager removeItemAtPath:[_documentsDirectory1 stringByAppendingPathComponent:@"1.zip"] error:nil];
}
邓肯

您对线程/队列的处理是错误的。

NSOperationQueue除非您将其专门设置为使用在主线程上运行的队列,否则将在作为后台队列的上调用NSURLSession委托方法

因此,您可以在委托方法中完成耗时的操作,而不会阻塞UI。

但是,任何更新UI的代码都需要在主线程上执行。

您可以摆脱dispatch_async(dispatch_get_global_queue解压缩代码周围包装器,因为除非采取特殊步骤,否则无论如何都会从后台线程调用该代码。

但是,会话委托方法中用于更新标签并进行其他UIKit调用的代码需要在主线程上执行:

- (void)URLSession:(NSURLSession *)session 
    downloadTask:(NSURLSessionDownloadTask *)downloadTask 
    didFinishDownloadingToURL:(NSURL *)location{

    if (downloadTask == _downloadTask1) {

        self.paths1 = NSSearchPathForDirectoriesInDomains(
            NSDocumentDirectory, NSUserDomainMask, YES);
        self.documentsDirectory1 = [_paths1 objectAtIndex:0];
        NSFileManager *fileManager = [NSFileManager defaultManager];
        NSURL *newLocation = [NSURL URLWithString: 
            [NSString stringWithFormat: @"file://%@/1.zip", 
        self.documentsDirectory1]];
        NSError *error;
        [fileManager copyItemAtURL:location toURL:newLocation error:&error];
        [self zip];
        [self removeZip];
    }
}

    - (void)URLSession:(NSURLSession *)session 
            downloadTask: (NSURLSessionDownloadTask *) downloadTask 
            didWriteData: (int64_t) bytesWritten  
            totalBytesWritten: (int64_t) totalBytesWritten
            totalBytesExpectedToWrite:(int64_t) totalBytesExpectedToWrite; {
        if (downloadTask == _downloadTask1) {
            self.progress1 = (float) totalBytesWritten;
            self.total1 =  (float) totalBytesExpectedToWrite;
            self.percentage = [NSString stringWithFormat:@"%.f%%", 
                ((_progress1 / _total1) * 100)];
            NSLog(@"%.f%%", self.percentage, );
    
            //Setting a label's text is a UI call so it needs to be done on the main thread
            dispatch_async(dispatch_get_main_queue(), ^{
                if ([_percentage isEqual: @"100%"]) {
                    _label.text = @«ok»;
                };
                else {
                    _label.text = _percentage;
                }
        }
    }


-(void) zip {
    _paths1 = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    _documentsDirectory1 = [_paths1 objectAtIndex:0];
    _zipPath1 = [_documentsDirectory1 stringByAppendingPathComponent:@"1.zip"];
    _destinationPath1 = [NSString stringWithFormat:@"%@",_documentsDirectory1];
    [SSZipArchive unzipFileAtPath:_zipPath1 toDestination:_destinationPath1];
}

-(void) removeZip {
    _paths1 = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    _documentsDirectory1 = [_paths1 objectAtIndex:0];
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSString *filename = [_documentsDirectory1 stringByAppendingPathComponent:@"1.zip"];
    [fileManager removeItemAtPath: filename error:nil];
}

顺便说一句,这条线是不必要的复杂和低效的:

_progress1 = [[NSNumber numberWithInteger:totalBytesWritten] floatValue];

没有理由创建一个NSNumber(需要内存分配的对象)。只需将其totalBytesWritten直接转换为浮点数即可:

self.progress1 = (float) totalBytesWritten;

并且,由于该代码在后台线程上运行,因此您应该使这些属性成为原子属性,并使用语法“ self.property”来使用该属性的getter和setter。

编辑:

上面的方法中还有其他我未解决的UI调用。我只是以其中之一为例进行了更改。

您处理100%完整的案件也是脆弱和不道德的做法。删除该代码,然后将调用您的(un)zip方法的代码移至完整的下载委托调用中,并删除performSelectorwithObject:afterDelay:这些调用周围包装器。

在下载完整的会话委托方法中,移动文件,解压缩并删除它,所有这些都无需调用dispatch_async,因为无论如何该方法都将在后台线程上调用。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章