iOS - 后台进程和UI更新
问题很简单:我的应用程序控制是否每次启动时都有更新。如果有更新,弹出窗口将显示“是”或“否”选择。当用户点击是4种方法启动。这些方法下载xml文件并上传CoreData。这是警报的代码:iOS - 后台进程和UI更新
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex==1) {
[self showActivityViewer];
[self downloadControlAndUpdatePoi];
[self downloadControlAndUpdateItinerari];
[self downloadControlAndUpdateArtisti];
[self downloadControlAndUpdateEventi];
[self hideActivityViewer];
NSLog(@"AGGIORNA");
} else {
NSLog(@"NON AGGIORNARE");
return;
}
}
但有一个问题:当用户水龙头是警告不会消失,并保留在屏幕上,直到所有的方法完成。所以我试试这个其他代码:
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex==1) {
[self showActivityViewer];
[NSThread detachNewThreadSelector:@selector(startDownloads) toTarget:self withObject:nil];
[self hideActivityViewer];
NSLog(@"AGGIORNA");
} else {
NSLog(@"NON AGGIORNARE");
return;
}
}
-(void)startDownloads {
NSInvocationOperation *opPoi=[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadControlAndUpdatePoi) object:nil];
NSInvocationOperation *opItinerari=[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadControlAndUpdateItinerari) object:nil];
NSInvocationOperation *opArtisti=[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadControlAndUpdateArtisti) object:nil];
NSInvocationOperation *opEventi=[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadControlAndUpdateEventi) object:nil];
NSArray *operations=[[NSArray alloc] initWithObjects:opPoi,opItinerari,opArtisti,opEventi, nil];
NSOperationQueue *queue=[[NSOperationQueue alloc] init];
[queue addOperations:operations waitUntilFinished:YES];
[queue waitUntilAllOperationsAreFinished];
}
甚至在这里还有一个问题:我点击开始,但活动查看器没有出现。警报消失,线程开始并运行4种方法。
我需要在后台运行的进程,就像我的第二代码发生,但我需要我的showActityViewer方法将运行并显示微调。
谢谢:)
第一件事第一件事。您不需要启动4个操作,因为您已经在辅助线程中,并且不需要并行执行4个操作。你可以简单地做:
-(void)startDownloads {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[self downloadControlAndUpdatePoi];
[self downloadControlAndUpdateItinerari];
[self downloadControlAndUpdateArtisti];
[self downloadControlAndUpdateEventi];
[pool release];
}
首先,你需要在startDownloads
定义一个自动释放池,如果你使用的downloadControl*
方法autorelease
,否则我怀疑你将有泄漏。
至于为什么活动的指标显示不出来,这取决于事实,你在呼唤:
[self hideActivityViewer];
分离之后。因此,您在显示UI并将其删除之前,UI已经有时间进行更新了。从那里取出该行并重写startDownloads
这样的:
-(void)startDownloads {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[self downloadControlAndUpdatePoi];
[self downloadControlAndUpdateItinerari];
[self downloadControlAndUpdateArtisti];
[self downloadControlAndUpdateEventi];
[self performSelectorOnMainThread:@selector(hideActivityViewer) withObject:nil waitUntilDone:NO];
[pool release];
}
这里请注意,我打电话到主线程hideActivityViewer
因为只有主线程可以安全地使用UIKit
。 编辑:
我不知道你在下载的方法,使用核心数据...
看一看Concurrency with Core Data。您至少需要为您的辅助线程使用单独的托管对象上下文来调整您的代码(我不知道在那里创建moc是否可行)。
也看看this tutorial from Cocoa is my Girlfriend。
作为替代一切,你可以考虑做:
if (buttonIndex==1) {
[self showActivityViewer];
[self performSelector:@selector(startDownloads) withObject:nil afterDelay:0];
NSLog(@"AGGIORNA");
} else {
NSLog(@"NON AGGIORNARE");
return;
}
有:
-(void)startDownloads {
[self downloadControlAndUpdatePoi];
[self downloadControlAndUpdateItinerari];
[self downloadControlAndUpdateArtisti];
[self downloadControlAndUpdateEventi];
[self hideActivityViewer];
}
这不使用线程所有,但我不知道该活动观众会显示没有任何故障。如果需要,还有一个级别的黑客,你可以指定延迟
[self performSelector:@selector(startDownloads) withObject:nil afterDelay:0.1];
但我该如何调用startDownloads?在用户点击“是”之后,是否有NSThread分离或[自启动下载]? –
对不起,用detachThread;你正确地做到了这一点。唯一的一点是,在startDownloads中,你不需要更多的异步操作,它们可以是顺序的。 – sergio
似乎它是一切都好,但一个问题,大问题发生了:我的downloadAndControl *方法与CoreData一起工作,并与此解决方案我有一个NSInternalInconsistencyException与CoreData的方法保存。 –