为什么子线程无法立刻停止 UIActivityIndicatorView 动画

2015-12-11 04:02:15 +08:00
 UtopiaCHN

相关代码:

UIActivityIndicatorView *confirmIndicatorView = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];

[confirmIndicatorView startAnimating];    

NSLog(@"正在登录"); 

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
         [NSThread sleepForTimeInterval:3];
         [confirmIndicatorView stopAnimating];
          NSLog(@"登录结束");
    });

运行结果:已经打印“登录结束”,但是 UIActivityIndicatorView 动画仍在运行,过了六七秒才结束。

3406 次点击
所在节点    iDev
20 条回复
nagato
2015-12-11 04:44:49 +08:00
[confirmIndicatorView stopAnimating] 得在主线程执行
UtopiaCHN
2015-12-11 04:48:58 +08:00
@nagato 放主线程那不是立即被执行了,动画都没有。
txx
2015-12-11 06:37:42 +08:00
要是 Android 你早就崩出去了......

UI 操作一定要在主线程,哪怕在子线程看起来没问题
hohoho
2015-12-11 09:15:06 +08:00
额,这个有多解的。比如用 gcd 的 after ,再比如把你的 stopanimating 放到嵌套的主线程 async 中
sagnitude
2015-12-11 09:30:36 +08:00
dispatch_get_global_queue 改成 dispatch_get_main_queue()

另外,应该用 NSTimer ,而不是 Thread.sleep
也可以用 performSelector 设定延时
altair21
2015-12-11 09:31:52 +08:00
ui 更新只能在主线程进行
XcodeUser
2015-12-11 09:37:33 +08:00
子线程的 UI 操作不会主动去绘制到屏幕上,只有在 UI 有更新(主线程)或者触摸事件的时候,才会重新绘制的时候, 顺带把子线程的 UI 操作效果展现出来。至于问题的解决方式,如 @hohoho 所说,嵌套一个主线程 operation 就行了
XcodeUser
2015-12-11 09:40:57 +08:00
一句话,子线程是确切的改变的 UI 的属性,但是这些改变不会即时 的绘制到屏幕上。
dorentus
2015-12-11 10:09:58 +08:00
@UtopiaCHN

只要把 [confirmIndicatorView stopAnimating]; 放在主线程里面,类似这样应该就可以:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[NSThread sleepForTimeInterval:3];
dispatch_async(dispatch_get_main_queue(), ^{
[confirmIndicatorView stopAnimating];
NSLog(@"登录结束");
});
});
xjbeta
2015-12-11 13:08:14 +08:00
主线程更新 UI
mornlight
2015-12-11 13:10:41 +08:00
不要在任何子线程上改动 UI 层的东西,你这还好没 crash 。
mornlight
2015-12-11 13:21:44 +08:00
在 block 里让 thread sleep 也是不对的。如果你的这个登录操作是 HTTP 请求,应该写到请求的 success block 里而不是强行等待几秒。这个代码是让 block 里的东西延迟 3 秒在主线程执行,没有阻塞效果:

```
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC),dispatch_get_main_queue(), ^{
//weakify self if need
[confirmIndicatorView stopAnimating];
NSLog(@"登录结束");
});
```
UtopiaCHN
2015-12-13 01:10:00 +08:00
@hohoho 谢谢
UtopiaCHN
2015-12-13 01:11:37 +08:00
@sagnitude 谢谢,为什么不能用 Thread.sleep 呢
UtopiaCHN
2015-12-13 01:12:11 +08:00
@XcodeUser 谢谢
UtopiaCHN
2015-12-13 01:12:40 +08:00
@dorentus 谢谢
UtopiaCHN
2015-12-13 01:13:37 +08:00
@xjbeta 谢谢
UtopiaCHN
2015-12-13 01:18:31 +08:00
@mornlight 很感谢,为什么不能在 block 里面 thread sleep 呢
mornlight
2015-12-13 01:45:27 +08:00
@UtopiaCHN 可以 sleep ,但是不要 sleep 主线程,那样 UI 就卡死了。
UtopiaCHN
2015-12-13 02:24:52 +08:00
@mornlight 好的,谢谢

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/242706

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX