iOS:在调用 view.hidden = NO 之后,有没有办法确定 UIView 何时出现
Posted
技术标签:
【中文标题】iOS:在调用 view.hidden = NO 之后,有没有办法确定 UIView 何时出现【英文标题】:iOS: Is there a way to determine when an UIView did appear, after calling view.hidden = NO 【发布时间】:2011-05-31 16:37:29 【问题描述】:我有一个带有 8 到 10 个大图像(每个都加载到 UIImageView 中)作为子视图的 UIView。这些图像彼此相邻对齐,因此它们构成了一个真正的长水平图像。这个视图被放入一个 UIScrollView 中,这样用户就可以沿着这个长长的水平图像滚动。
加载所有这些图像(来自网络)需要相当长的时间,所以我决定将加载代码放入 NSOperation 子类中。在操作的 main 方法中,每个 ImageView 都被添加到容器视图中。
在此过程中视图被隐藏,取而代之的是一个小的旋转图像(很像 UIActivityIndicatorView)。这是一些代码:
CategoryViewController.m
- (id)initWithFrame:(CGRect)frame
self = [super init];
if(self)
// do some unrelated stuff
[...]
loadIndicator = [[UIImageView alloc] initWithImage:img];
[loadIndicator setFrame:CGRectMake((frame.size.width - width) / 2, (frame.size.height - height) / 2, width, height)];
[loadIndicator setHidden:YES];
// this is the view which will contain those large images
backgroundView = [[UIView alloc] init];
backgroundView.hidden = YES;
scrollView = [[UIScrollView alloc] initWithFrame:frame];
[scrollView setDelegate:(id<UIScrollViewDelegate>)self];
[scrollView addSubview:backgroundView];
[self.view setFrame:frame];
return self;
- (void)viewDidLoad
// do some unrelated stuff
[...]
[self.view addSubview:loadIndicator];
[self.view addSubview:scrollView];
// setup a custom activity indicator
loadIndicator.hidden = NO;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDelegate:self];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
loadIndicatorRotation = 0;
rotationTimer = [NSTimer scheduledTimerWithTimeInterval: 0.01 target: self selector:@selector(updateRotation:) userInfo: nil repeats: YES];
[UIView commitAnimations];
// setup the operation to load all background images
operationQueue = [[NSOperationQueue alloc] init];
LoadBackgroundImagesOperation* operation = [[LoadBackgroundImagesOperation alloc] initWithImages:bgImageNames View:backgroundView Frame:frame];
// register to recieve the finish notification
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onFinishedLoadingBgImages) name:@"BgImagesFinishedLoading" object:operation];
// Add the operation to the queue
[operationQueue addOperation:operation];
[operation release];
[super viewDidLoad];
LoadBackgroundImagesOperation.m的主要方法
- (void)main
int left = 0;
int width, height;
int i;
for(i = 0; i < imageNames.count; i++)
if([self isCancelled])
[[NSNotificationCenter defaultCenter] postNotificationName:@"BgImagesCancelled" object:self];
return;
// code to retrieve the url of current image
[...]
NSData* data = [[NSData alloc] initWithContentsOfURL:imgURL];
UIImage* image = [[UIImage alloc] initWithData:data];
[data release];
double scalingFactor = frame.size.height / image.size.height;
width = image.size.width * scalingFactor;
height = image.size.height * scalingFactor;
UIImageView* imgView = [[UIImageView alloc] initWithImage:image];
[image release];
[imgView setFrame:CGRectMake(left, 0, width, height)];
[background addSubview:imgView];
[imgView release];
left += width;
[background setFrame:CGRectMake(0, 0, left, height)];
[[NSNotificationCenter defaultCenter] postNotificationName:@"BgImagesFinishedLoading" object:self];
操作完成后,我隐藏旋转图像并显示包含大图像的视图。
(再次返回 CategoryViewController.m)
- (void) onFinishedLoadingBgImages
[scrollView setContentSize:backgroundView.frame.size];
backgroundView.hidden = NO;
loadIndicator.hidden = YES;
if(operationQueue != nil)
[operationQueue cancelAllOperations];
[operationQueue release];
operationQueue = nil;
[rotationTimer invalidate];
rotationTimer = nil;
问题是,在调用backgroundView.hidden = NO
后,直到图像真正可见,模拟器需要大约 2 秒,而在真实设备上最多需要 5 秒。
在那段时间我会继续显示活动指示器,但我不知道如何检测到 backgroundview
确实出现了以便再次隐藏指示器。
我尝试将backgroundview
放在它自己的 UIViewController 中,并在调用 viewDidAppear 时通知我的父视图控制器,但这不起作用。 (我在嵌套视图控制器中读到过,我必须手动调用 viewDidAppear,但这不是一个选项,因为我不知道它何时出现)。
另外,我不能只做肮脏的把戏,改变backgroundView
和loadIndicator
的顺序来隐藏它,因为大多数图像都有一些透明度,所以用户仍然会看到指示器。
所以我真的希望你们中的任何人都对如何检测backgroundview
何时真正可见提出建议。
谢谢, 克里斯
哦,抱歉,如果某些代码与问题无关。只是想向您介绍我正在做的事情。
【问题讨论】:
【参考方案1】:您可以做的是创建一个 UIViewController 子类,并使其成为该视图的所有者,在该方法中,您可以尝试将所需的代码放入 viewDidLoad 方法中,看看是否更准确,但是我认为真正的问题是您使用的 imageViews 正在花时间加载图像,而不是 UIView。因此,UIView 是可见的,但是 imageViews 还没有加载它们的图像,所以你什么都看不到。
【讨论】:
这就是我所怀疑的。我认为也许有一种方法可以确定 imageViews 何时出现,但我想没有。【参考方案2】:如果您在滚动视图中显示大量大图像,您应该真正考虑平铺它们,以便可以单独加载部分图像,并且您不必在内存中保留多个大图像同时。查看CATiledLayer 和PhotoScroller 示例代码。
【讨论】:
感谢您提供示例链接。我去看看。以上是关于iOS:在调用 view.hidden = NO 之后,有没有办法确定 UIView 何时出现的主要内容,如果未能解决你的问题,请参考以下文章
iOS-报错“No visible @interface for ‘NSObject‘ declares the selector ‘XXXX:‘”