UIButton 选择器的状态和进度
Posted
技术标签:
【中文标题】UIButton 选择器的状态和进度【英文标题】:UIButton State and progress of selector 【发布时间】:2013-04-03 12:09:32 【问题描述】:我在显示较长主线程操作的进度时遇到了一些问题(需要在主线程中)。
通过按下按钮调用动作。
-(void)getCSVExport:(id)sender
...
NSString *filePath = [path stringByAppendingPathComponent:fileName];
NSData *csvData = [NSData dataWithContentsOfFile:filePath];
if (nil == csvData)
_progressView.hidden = NO;
[self.view bringSubviewToFront:_progressView];
_progressView.progress = 0;
csvData = [self generateCSVExportForMonth:_monthToExportInt];
[csvData writeToFile:filePath atomically:YES];
_progressView.hidden = YES;
...
在功能generateCSVExportForMonth:
内,我正在使用_progressView.progress = newValue
更新进度。
我现在有两个问题:
1) 当按下呼叫getCSVExport:
的按钮时,该按钮保持突出显示,直到呼叫完成。
2) progressView 永远不会出现,更不用说自我更新了。
信息:通话需要 0.5 到 2 秒,具体取决于设备。
任何想法我哪里出错了?
// 编辑:带有背景线程的新版本:
[self.view bringSubviewToFront:_progressView];
_progressView.progress = 0;
[self performSelector:@selector(assignCSVData:) onThread:[NSThread new] withObject:csvData waitUntilDone:YES];
_progressView.hidden = YES;
以及耗时的通话:
-(void)assignCSVData:(NSData*)data
data = [self generateCSVExportForMonth:_monthToExportInt];
这会导致performSelector
调用出现死锁。
【问题讨论】:
【参考方案1】:问题是你的主线程被阻塞了。这正是为需要更长时间的事情使用后台线程的原因,因为您不希望 GUI 冻结。
我不明白为什么像解析 CSV 文件这样的东西绝对必须在主线程上。您必须在后台执行此操作(或者忍受冻结 GUI 的糟糕用户体验)。
你有几个选择如何实际实现这样的东西。
使用NSObject
的performSelectorInBackground:withObject:
将解析代码放在一个单独的方法中,并在后台线程上使用:
[self performSelectorInBackground:@selector(parseMethod) withObject:csvData];
在该方法结束时,您在主线程上调用某个方法以通知它解析已完成。
[self performSelectorOnMainThread:@selector(parsingDone:) withObject:result waitUntilDone:NO];
使用Grand Central Dispatch (GCD) 使用块语法在后台运行一些代码。如果您习惯于 Objective-C 和 Cocoa API,也很简单,但语法和语义会稍微复杂一些。
使用NSOperation
和NSOperationQueue
。对于您的目的,可能会有一点开销。尽管您也可以通过调用 addOperationWithBlock
轻松地将新操作添加到队列中,而无需子类化 NSOperation
。
【讨论】:
我的问题是生成csv文件的方法访问coredata。我过去因此而陷入僵局,并希望避免这种情况。让用户在应用程序的生命周期中最多等待 2 秒——报告永远不会被重新创建,而是存储和重用——是我确保稳定性的计划。另一种方法是,我需要确保应用程序保持在同一个位置(视图控制器),直到生成报告,因为它将在那里使用:/如果有一种聪明的方法,我会很高兴好吧:) 它是否一直依赖于 Cora Data 对象?难道你不能只获取你需要的那些对象并在后台将它们传递给解析器吗? 报告准确地进行了 5+(numberOfDaysOfMonth) 次提取,并不断分布在函数执行中。对象和属性提取之间的提取差异很大。由于对结果进行繁琐的排序,一次获取所有内容会造成很大的性能损失。 建议我可以让它成为线程安全的。我将如何在另一个线程中调用csvData = [self generateCSVExportForMonth:_monthToExportInt];
?这是一个耗时的电话。
你需要对 Core Data 和后台线程有些小心。 从不 将实际的NSManagedObject
传递给不同的线程(只有对象 ID)。更好的是,在后台线程中创建一个单独的NSManagedObjectContext
。但如果这真的最多只需要 2 秒,您可能可以在主线程上执行此操作并使用一些 run loop trickery 更新进度条...以上是关于UIButton 选择器的状态和进度的主要内容,如果未能解决你的问题,请参考以下文章