代码之家  ›  专栏  ›  技术社区  ›  Ben Collins

视图不是更新,而是主线程上的所有内容

  •  2
  • Ben Collins  · 技术社区  · 15 年前

    我试图在特定用户交互之后在表视图的顶部显示一个uiprogressview。在我的表视图中,如果用户点击一个特定的单元格,我会向上滑动一个uiview,该uiview包含一个带有条形图项的工具栏和一个选择器视图(它的行为非常类似于操作表)。当我这样做时,我将把屏幕外的视图添加到当前视图中,然后为幻灯片设置动画。当用户进行选择并点击“完成”时,视图将滑出。此时,进度视图应该在后台发生某些事情时显示和更新。

    我遇到的问题是,当“警报表”ui view从当前视图中滑出后,在一段时间内,ui中不会发生任何事情。当我显示滑动视图时,我执行以下操作:

    [[[UIApplication sharedApploication] keyWindow] addSubview:slidingView];
    CGRect newFrame = CGRectMake(...);
    [UIView animateWithDuration:0.3
        animations:^{
            slidingView.frame = newFrame;
        }];
    

    当用户点击滑动视图中的“完成”按钮时,将调用此操作方法:

    - (void) done {
        NSNumber *row = GetSelectedRowSomehow();
    
        [self dismiss:@selector(doneCallback:) withObject:row];
    }
    
    - (void) dismiss:(SEL)cb withObject:(id)obj {
        [UIView animateWithDuration:0.3
            animations:^{
                slidingView.frame = CGRectMake(...);
            }
            completion:^(BOOL finished) {
                [self.delegate performSelectorOnMainThread:cb
                                                withObject:obj
                                             waitUntilDone:NO];
                [slidingView performSelectorOnMainThread:@selector(removeFromSuperview:)
                                              withObject:nil
                                           waitUntilDone:NO];
            }];
    }
    

    在此处调用的回调:

    - (void) doneCallback {
        self.dialogView.hidden = NO;
        self.progressView.progress = 0;
    
        for (float i = 0; i < 1.0; i += 0.1) {
            self.progressView.progress += i;
            sleep(0.5);
        }
    }
    

    在我看来, dialogView 以后才出现 callback 已完成。为什么不在它的 hidden 属性设置为 NO ?

    1 回复  |  直到 15 年前
        1
  •  2
  •   JosephH    15 年前

    一旦代码完成执行,主线程中的显示就会更新,因此通过阻塞主线程,可以防止这种情况发生。

    其中一个原因是更新被批处理在一起,以便能够有效地重新绘制。

    解决方案/解决方法之一是使用performselector:after delay:0.01 to在donecallback中hidden=no之后,将以下代码移动到延迟之后运行的新选择器中。

    或者,您可以将“doneCallback”中的代码作为后台操作来运行(尽管您不能直接从后台线程更新uikit,因此您必须向主线程发送消息以进行任何显示更新)。

    推荐文章