V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
iOS 开发实用技术导航
NSHipster 中文版
http://nshipster.cn/
cocos2d 开源 2D 游戏引擎
http://www.cocos2d-iphone.org/
CocoaPods
http://cocoapods.org/
Google Analytics for Mobile 统计解决方案
http://code.google.com/mobile/analytics/
WWDC
https://developer.apple.com/wwdc/
Design Guides and Resources
https://developer.apple.com/design/
Transcripts of WWDC sessions
http://asciiwwdc.com
Cocoa with Love
http://cocoawithlove.com/
Cocoa Dev Central
http://cocoadevcentral.com/
NSHipster
http://nshipster.com/
Style Guides
Google Objective-C Style Guide
NYTimes Objective-C Style Guide
Useful Tools and Services
Charles Web Debugging Proxy
Smore
UtopiaCHN
V2EX  ›  iDev

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

  •  
  •   UtopiaCHN · 2015-12-11 04:02:15 +08:00 · 3267 次点击
    这是一个创建于 3060 天前的主题,其中的信息可能已经有所发展或是发生改变。

    相关代码:

    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 动画仍在运行,过了六七秒才结束。

    20 条回复    2015-12-13 02:24:52 +08:00
    nagato
        1
    nagato  
       2015-12-11 04:44:49 +08:00   ❤️ 1
    [confirmIndicatorView stopAnimating] 得在主线程执行
    UtopiaCHN
        2
    UtopiaCHN  
    OP
       2015-12-11 04:48:58 +08:00
    @nagato 放主线程那不是立即被执行了,动画都没有。
    txx
        3
    txx  
       2015-12-11 06:37:42 +08:00 via iPhone   ❤️ 1
    要是 Android 你早就崩出去了......

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

    另外,应该用 NSTimer ,而不是 Thread.sleep
    也可以用 performSelector 设定延时
    altair21
        6
    altair21  
       2015-12-11 09:31:52 +08:00 via iPhone   ❤️ 1
    ui 更新只能在主线程进行
    XcodeUser
        7
    XcodeUser  
       2015-12-11 09:37:33 +08:00   ❤️ 1
    子线程的 UI 操作不会主动去绘制到屏幕上,只有在 UI 有更新(主线程)或者触摸事件的时候,才会重新绘制的时候, 顺带把子线程的 UI 操作效果展现出来。至于问题的解决方式,如 @hohoho 所说,嵌套一个主线程 operation 就行了
    XcodeUser
        8
    XcodeUser  
       2015-12-11 09:40:57 +08:00
    一句话,子线程是确切的改变的 UI 的属性,但是这些改变不会即时 的绘制到屏幕上。
    dorentus
        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(@"登录结束");
    });
    });
    xjbeta
        10
    xjbeta  
       2015-12-11 13:08:14 +08:00   ❤️ 1
    主线程更新 UI
    mornlight
        11
    mornlight  
       2015-12-11 13:10:41 +08:00
    不要在任何子线程上改动 UI 层的东西,你这还好没 crash 。
    mornlight
        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(@"登录结束");
    });
    ```
    UtopiaCHN
        13
    UtopiaCHN  
    OP
       2015-12-13 01:10:00 +08:00
    @hohoho 谢谢
    UtopiaCHN
        14
    UtopiaCHN  
    OP
       2015-12-13 01:11:37 +08:00
    @sagnitude 谢谢,为什么不能用 Thread.sleep 呢
    UtopiaCHN
        15
    UtopiaCHN  
    OP
       2015-12-13 01:12:11 +08:00
    @XcodeUser 谢谢
    UtopiaCHN
        16
    UtopiaCHN  
    OP
       2015-12-13 01:12:40 +08:00
    @dorentus 谢谢
    UtopiaCHN
        17
    UtopiaCHN  
    OP
       2015-12-13 01:13:37 +08:00
    @xjbeta 谢谢
    UtopiaCHN
        18
    UtopiaCHN  
    OP
       2015-12-13 01:18:31 +08:00
    @mornlight 很感谢,为什么不能在 block 里面 thread sleep 呢
    mornlight
        19
    mornlight  
       2015-12-13 01:45:27 +08:00   ❤️ 1
    @UtopiaCHN 可以 sleep ,但是不要 sleep 主线程,那样 UI 就卡死了。
    UtopiaCHN
        20
    UtopiaCHN  
    OP
       2015-12-13 02:24:52 +08:00
    @mornlight 好的,谢谢
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2976 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 14:03 · PVG 22:03 · LAX 07:03 · JFK 10:03
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.