iOS GUI刷新

时间:2014-07-07 13:40:10

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

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

我有以下管道:

1)应用程序来自后台 - 名为applicationWillEnterForeground

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

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

3)使用dispatch_asyncdispatch_get_main_queue()一起使用新数据填充标签,图片等

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

问题是,调用了步骤3.1,但只是不时地改变apper。如果我交换页面,刷新完成,我可以看到新数据(所以下载工作正常)。但是没有手动翻页,就没有更新。

任何帮助?

编辑:来自步骤3和3.1的代码(删除了注释中指向的_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];
} 

在MainViewController中

-(void)UpdateData
{

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

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

3 个答案:

答案 0 :(得分:1)

试试这个:

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

或查看此链接:

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

答案 1 :(得分:0)

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

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

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


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

答案 2 :(得分:0)

所提议的解决方案均无效。所以最后,我只是从UIPageControllView删除当前显示的屏幕并再次添加此屏幕。有点像改变页面然后再以编程方式返回。

它有点慢,但工作正常。