
相关代码:
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 [confirmIndicatorView stopAnimating] 得在主线程执行 |
3 txx 2015-12-11 06:37:42 +08:00 via iPhone 要是 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 dispatch_get_global_queue 改成 dispatch_get_main_queue() 另外,应该用 NSTimer ,而不是 Thread.sleep 也可以用 performSelector 设定延时 |
6 altair21 2015-12-11 09:31:52 +08:00 via iPhone ui 更新只能在主线程进行 |
7 XcodeUser 2015-12-11 09:37:33 +08:00 子线程的 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 @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 主线程更新 UI |
11 mornlight 2015-12-11 13:10:41 +08:00 不要在任何子线程上改动 UI 层的东西,你这还好没 crash 。 |
12 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(@"登录结束"); }); ``` |