相关代码:
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 动画仍在运行,过了六七秒才结束。
1
nagato 2015-12-11 04:44:49 +08:00 1
[confirmIndicatorView stopAnimating] 得在主线程执行
|
3
txx 2015-12-11 06:37:42 +08:00 via iPhone 1
要是 Android 你早就崩出去了......
UI 操作一定要在主线程,哪怕在子线程看起来没问题 |
4
hohoho 2015-12-11 09:15:06 +08:00 via iPhone
额,这个有多解的。比如用 gcd 的 after ,再比如把你的 stopanimating 放到嵌套的主线程 async 中
|
5
sagnitude 2015-12-11 09:30:36 +08:00 1
dispatch_get_global_queue 改成 dispatch_get_main_queue()
另外,应该用 NSTimer ,而不是 Thread.sleep 也可以用 performSelector 设定延时 |
6
altair21 2015-12-11 09:31:52 +08:00 via iPhone 1
ui 更新只能在主线程进行
|
7
XcodeUser 2015-12-11 09:37:33 +08:00 1
子线程的 UI 操作不会主动去绘制到屏幕上,只有在 UI 有更新(主线程)或者触摸事件的时候,才会重新绘制的时候, 顺带把子线程的 UI 操作效果展现出来。至于问题的解决方式,如 @hohoho 所说,嵌套一个主线程 operation 就行了
|
8
XcodeUser 2015-12-11 09:40:57 +08:00
一句话,子线程是确切的改变的 UI 的属性,但是这些改变不会即时 的绘制到屏幕上。
|
9
dorentus 2015-12-11 10:09:58 +08:00 1
@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(@"登录结束"); }); }); |
10
xjbeta 2015-12-11 13:08:14 +08:00 1
主线程更新 UI
|
11
mornlight 2015-12-11 13:10:41 +08:00
不要在任何子线程上改动 UI 层的东西,你这还好没 crash 。
|
12
mornlight 2015-12-11 13:21:44 +08:00 1
在 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(@"登录结束"); }); ``` |