iOS: Est-il un moyen de déterminer quand une UIView apparaître, après l'appel de la vue.hidden = PAS de

J'ai une UIView avec 8 à 10 grandes images (chaque chargé dans une UIImageView) comme des sous-vues. Ces images sont alignées les unes à côté des autres, de sorte qu'ils composent un vrai long horizontale de l'image. Ce point de vue est placé dans un UIScrollView, de sorte que l'utilisateur peut faire défiler le long de cette longue horizontale de l'image.

Le chargement de toutes les images (sur le web) prend du temps, j'ai donc décidé de mettre que le code de chargement dans un NSOperation sous-classe. À l'intérieur de l'opération principale de la méthode chaque ImageView est ajouté au conteneur de vue.

La vue est cachée pendant ce processus, et à la place il y a une petite rotation de l'image (un peu comme un UIActivityIndicatorView). Voici un code:

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];
}

principale méthode de 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];
}

Lorsque l'opération est terminée, je me cache dans la rotation de l'image et de montrer le point de vue, qui contient les images de grande taille.

(de retour dans CategoryViewController.m nouveau)

- (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;
}

Le problème est que cela prend environ 2 secondes pour que le simulateur et jusqu'à 5 secondes sur le réel de l'appareil jusqu'à ce que les images sont vraiment visibles après l'appel de backgroundView.hidden = NO

Je vais simplement continuer à montrer l'indicateur d'activité pendant cette période, mais je ne sais pas comment faire pour détecter backgroundview n'apparaissent dans l'ordre pour masquer l'indicateur de nouveau.

J'ai essayé de mettre backgroundview dans son propre UIViewController et avertir mes parents-vue-contrôleur lorsque viewDidAppear est appelé, mais qui ne fonctionne pas. (J'ai lu que dans les contrôleurs de vue que je devrais l'appeler viewDidAppear manuellement, mais ce n'est pas une option, parce que je ne sais pas quand il est apparu dans la première place).

Aussi, je ne peux pas juste faire le sale truc et modifier l'ordre de backgroundView et loadIndicator de le cacher, parce que la plupart des images ont une certaine transparence en eux, de sorte que l'utilisateur puisse toujours voir l'indicateur.

Donc j'espère vraiment que l'un de vous les gars avez des suggestions sur la façon de détecter quand backgroundview est réellement visible.

Grâce,
Chris

Oh, et désolé si le code est un peu sans rapport avec le problème. Voulais juste vous donner une vue d'ensemble de ce que je fais.

OriginalL'auteur christoph | 2011-05-31