У меня есть UIView с 8-10 большими изображениями (каждое загружено в UIImageView) в качестве подпредставлений.Эти изображения выровнены рядом друг с другом, так что они составляют очень длинное горизонтальное изображение.Это представление помещается в UIScrollView, так что пользователь может прокручивать это длинное горизонтальное изображение.
Загрузка всех этих изображений (из Интернета) занимает довольно много времени, поэтому я решил поместить этот код загрузки вПодкласс NSOperation.Внутри основного метода операции каждый 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
действительно виден.
Спасибо, Крис
О, и извините, если какой-то код несколько не связанк проблеме.Просто хотел дать вам общую картину того, что я делаю.