我有一个UIView,有8到10个大图像(每个加载到UIImageView中)作为子视图。这些图像彼此相邻排列,因此它们构成了一个真正的长水平图像。此视图放入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;
}
问题是模拟器需要大约2秒钟,真实设备需要5秒钟,直到调用backgroundView.hidden = NO
后图像实际可见
我会在此期间继续显示活动指示器,但我不知道如何检测backgroundview
确实出现以便再次隐藏指示器。
我尝试将backgroundview
放在自己的UIViewController中,并在调用viewDidAppear时通知我的父视图控制器,但这不起作用。 (我读到在嵌套视图控制器中我必须手动调用viewDidAppear,但这不是一个选项,因为我不知道它何时出现在第一位)。
此外,我不能只是做肮脏的技巧并改变backgroundView
和loadIndicator
的顺序来隐藏它,因为大多数图像都有一些透明度,所以用户仍然会看指标。
所以我真的希望,你们中的任何人都有关于如何检测backgroundview
何时实际可见的建议。
谢谢, 克里斯
哦,对不起,如果某些代码与问题有些无关。只是想让你了解我正在做的事情。
答案 0 :(得分:2)
你可以做的是创建一个UIViewController子类,并使其成为该视图的所有者,并且在该方法中,您可以尝试在viewDidLoad方法中放置所需的代码,看看是否更准确,但我认为真正的问题是你使用的imageViews正在花时间加载图像,而不是UIView。因此,UIView是可见的,但是imageViews还没有加载他们的图像,所以你什么也看不见。
答案 1 :(得分:1)
如果你在滚动视图中显示很多大图像,你应该考虑平铺它们,以便可以单独加载部分图像,而不必将几个大图像保存在内存中。同时。请查看CATiledLayer和PhotoScroller示例代码。