iOS GUI 刷新
Posted
技术标签:
【中文标题】iOS GUI 刷新【英文标题】:iOS GUI refresh 【发布时间】:2014-08-28 00:24:40 【问题描述】:我在我的 GUI 上使用 setNeedsDisplay,但有时没有完成更新。我使用的是UIPageControllView
,每个页面都有UIScrollView
,里面有UIView
。
我有以下管道:
1) 应用来自后台 - 称为applicationWillEnterForeground
2) 开始从服务器下载数据
2.1) 数据下载完成后,触发选择器
3) 使用dispatch_async
和dispatch_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 文件)都是链接的出口 【参考方案1】:setNeedsDisplay
触发drawRect:
并用于“重绘视图的像素”,而不是配置视图或其子视图。
您可以覆盖 drawRect:
并在那里修改您的标签等,但这不是它的用途,setNeedsLayout
/layoutSubviews
也不是。
您应该创建自己的 updateUI
方法,在该方法中使用新数据来更新 UI,而不是依赖专门用于重绘像素 (setNeedsDisplay
) 或调整子视图框架 (drawRect:
) 的系统调用。
您应该在updateUI
方法中设置所有label.text
、imageView.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
中删除了当前显示的屏幕并再次添加此屏幕。类似于以编程方式更改页面并再次返回。
它有点慢,但工作正常。
【讨论】:
以上是关于iOS GUI 刷新的主要内容,如果未能解决你的问题,请参考以下文章