从主队列的回调中更新 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的主要内容,如果未能解决你的问题,请参考以下文章

在 while 循环中更新 UIView 的背景颜色

直接从主 ViewController 加载另一个 UIView

UIStackView中UILabels上的动画隐藏属性导致不同的动画

UIView - 啥覆盖将允许更新 UIView 框架

UIVIew/CALayer 动画期间的回调

通过工作簿VBA从主列表更新价格