【问题标题】:iOS GUI refreshiOS GUI 刷新
【发布时间】:2014-08-28 00:24:40
【问题描述】:

我在我的 GUI 上使用 setNeedsDisplay,但有时没有完成更新。我使用的是UIPageControllView,每个页面都有UIScrollView,里面有UIView

我有以下管道:

1) 应用来自后台 - 称为applicationWillEnterForeground

2) 开始从服务器下载数据

2.1) 数据下载完成后,触发选择器

3) 使用dispatch_asyncdispatch_get_main_queue() 用新数据填充标签、图像等

3.1) 在视图上调用 setNeedsDisplay(也尝试在滚动视图和页面控制器上)

问题是,步骤 3.1 被调用,但只是不时发生变化。如果我交换页面,则刷新完成,我可以看到新数据(因此下载正常)。但是没有手动翻页,就没有更新。

有什么帮助吗?

编辑:步骤 3 和 3.1 中的代码(删除了 cmets 中指向的 _needRefresh 变量)

 -(void)FillData {
    dispatch_async(dispatch_get_main_queue(), ^{

    NSString *stateID = [DataManager  ConvertStateToStringFromID:_activeCity.actual_weather.state];

    if ([_activeCity.actual_weather.is_night boolValue] == YES)
    {
          self.contentBgImage.image = [UIImage imageNamed:[NSString stringWithFormat:@"bg_%@_noc", [_bgs objectForKey:stateID]]];

        if (_isNight == NO)
        {
            _bgTransparencyInited = NO;
        }

        _isNight = YES;

    }
    else
    {
        self.contentBgImage.image = [UIImage imageNamed:[NSString stringWithFormat:@"bg_%@", [_bgs objectForKey:stateID]]];

        if (_isNight == YES)
        {
            _bgTransparencyInited = NO;
        }

        _isNight = NO;

    }
    [self.contentBgImage setNeedsDisplay]; //refresh background image

    [self CreateBackgroundTransparency]; //create transparent background if colors changed - only from time to time


    self.contentView.parentController = self;
    [self.contentView FillData]; //Fill UIView with data - set labels texts to new ones

    //_needRefresh is set to YES after application comes from background

    [self.contentView setNeedsDisplay]; //This do nothing ?

    [_grad display]; //refresh gradient

}); 
}

这是数据下载后调用的选择器(在 MainViewController 中)

-(void)FinishDownload:(NSNotification *)notification
{
    dispatch_async(dispatch_get_main_queue(), ^{

        [_activeViewController FillData]; //call method shown before

        //try call some more refresh - also useless
        [self.pageControl setNeedsDisplay];

         //[self reloadInputViews];
         [self.view setNeedsDisplay];


    });

} 

在 AppDelegate 中,我有这个来自后台的应用程序:

-(void)applicationWillEnterForeground:(UIApplication *)application
{
    MainViewController *main = (MainViewController *)[(SWRevealViewController *)self.window.rootViewController frontViewController];


    [main UpdateData];
} 

在主视图控制器中

-(void)UpdateData
{

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(FinishForecastDownload:) name:@"FinishDownload" object:nil]; //create selector

    [[DataManager SharedManager] DownloadForecastDataWithAfterSelector:@"FinishDownload"]; //trigger download
}

【问题讨论】:

  • 你在 dispatch_async 块中调用 setNeedsDisplay 吗?如果是这种情况:需要在主线程上调用 setNeedsDisplay!
  • @SebastianBorggrewe 我用 dispatch_get_main_queue() 在 dispatch_async 中给他打电话
  • 能把dispatch块的代码贴出来吗?
  • @SebastianBorggrewe 添加了代码片段
  • 好的,只是为了澄清。您已确保 [self.contentView setNeedsDisplay];和 [self.pageControl setNeedsDisplay];实际上被称为(断点或 NSLog)并且两者(如果您使用故事板和/或 nib 文件)都是链接的出口

标签: ios objective-c user-interface refresh redraw


【解决方案1】:

setNeedsDisplay 触发drawRect: 并用于“重绘视图的像素”,而不是配置视图或其子视图。

您可以覆盖 drawRect: 并在那里修改您的标签等,但这不是它的用途,setNeedsLayout/layoutSubviews 也不是。

您应该创建自己的 updateUI 方法,在该方法中使用新数据来更新 UI,而不是依赖专门用于重绘像素 (setNeedsDisplay) 或调整子视图框架 (drawRect:) 的系统调用。


您应该在updateUI 方法中设置所有label.textimageView.image 等。此外,最好尝试仅通过此方法而不是直接通过任何方法设置这些值。

【讨论】:

  • 我应该在自己的 updateUI 中添加什么?我已经自己更改了所有标签,但唯一缺少的是那些新值是可见的。我仍然看到旧的。
【解决方案2】:

试试这个:

[self.view performSelectorOnMainThread:@selector(setNeedsLayout) withObject:nil waitUntilDone:NO];

或查看此链接:

http://blackpixel.com/blog/2013/11/performselectoronmainthread-vs-dispatch-async.html

【讨论】:

    【解决方案3】:

    建议的解决方案均无效。所以最后,我只是从UIPageControllView 中删除了当前显示的屏幕并再次添加此屏幕。类似于以编程方式更改页面并再次返回。

    它有点慢,但工作正常。

    【讨论】:

      猜你喜欢
      • 2018-09-18
      • 1970-01-01
      • 2012-03-09
      • 2019-11-30
      • 2012-01-17
      • 2015-11-17
      • 2014-09-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多