gpt4 book ai didi

ios - Objective-C:淡化 GUI

转载 作者:行者123 更新时间:2023-11-29 00:36:00 25 4
gpt4 key购买 nike

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

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];
}

最佳答案

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

NSURLSession 委托(delegate)方法在 NSOperationQueue 上调用,这是一个后台队列,除非您专门将其设置为使用在主线程上运行的队列。

因此,您可以在委托(delegate)方法中执行耗时的操作,而不会阻塞 UI。

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

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

但是,更新标签和进行其他 UIKit 调用的 session 委托(delegate)方法中的代码需要在主线程上执行:

- (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 直接转换为 float :

self.progress1 = (float) totalBytesWritten;

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

编辑:

上述方法中还有其他 UI 调用我没有修复。我只是更改了其中一个作为示例。

您对 100% 完整案例的处理也是脆弱和糟糕的做法。删除该代码并将调用您的 (un)zip 方法的代码移动到下载完成委托(delegate)调用,并删除围绕这些调用的 performSelectorwithObject:afterDelay: 包装器。

在下载完成 session 委托(delegate)方法中,移动文件、解压缩并删除它,所有这些都没有调用任何 dispatch_async,因为无论如何都会在后台线程上调用该方法。

关于ios - Objective-C:淡化 GUI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40611113/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com