从主队列的回调中更新 UIView 上的 UILabel
Posted
技术标签:
【中文标题】从主队列的回调中更新 UIView 上的 UILabel【英文标题】:Updating UILabel on UIView from the main queue's callback 【发布时间】:2013-11-01 16:51:48 【问题描述】:在我的 ios 应用中,用户可以打开从磁盘加载的项目。这需要一些时间,所以我展示了我的自定义加载视图,它是 UIView 的子类。这个加载视图有一个标签,它就像一个进度条。我正在尝试不断更新它的价值。
这是第一种方法(我稍微简化了我的代码):
// in view controller, which has projects list
[self performSelectorInBackground:@selector(openLoading) withObject:nil];
[projectsManager loadProject:project statusChangedCallback: ^(NSString* status)
self.loadingDialog.progressString = status;
];
[self closeLoading];
// in ProjectsManager
-(void) loadProject:(NSString*)project statusChangedCallback:(void(^)(NSString* status))callback
callback(@"Loading some data...");
[self loadSomeDataFrom:project];
callback(@"Loading other data...");
[self loadOtherDataFrom:project];
这种方法不起作用(UILabel 不更新),因为我在一个循环周期中从主队列多次更新它。我还尝试了不同的方法,例如:
[projectsManager loadProject:project statusChangedCallback: ^(NSString* status)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^
self.loadingDialog.progressString = status;
);
];
但是由于同样的原因,后台标签的这种更新也不起作用 - 主循环已停止。我想把我所有的项目加载都放到后台线程中,所以主循环不会受到影响,但这是不可能的,因为项目加载与一些只能在主线程中执行的 OpenGL 纹理加载密切相关。
我也尝试发送 -setNeedsDisplay 来查看,但这也不起作用。
那么,如何在主队列忙碌时更新标签?也许,我需要改变呈现加载视图的机制架构?
【问题讨论】:
【参考方案1】:值没有得到更新,因为您使用的是后台队列,并且无法在主线程 dispatch_get_global_queue
之外的任何线程中更新 UI,仍然使用后台线程,使用 dispatch_get_main_queue
进行任何更改用户界面。
试试:
dispatch_async(dispatch_get_main_queue(), ^ self.loadingDialog.progressString = 状态; )
【讨论】:
也试过了,还是不行……这段代码可能和没有dispatch_async
的代码几乎一样,因为所有都是在主队列中执行的。以上是关于从主队列的回调中更新 UIView 上的 UILabel的主要内容,如果未能解决你的问题,请参考以下文章
直接从主 ViewController 加载另一个 UIView