Note that there are some explanatory texts on larger screens.

plurals
  1. POiOS: Is there a way to determine when an UIView did appear, after calling view.hidden = NO
    primarykey
    data
    text
    <p>I have an UIView with 8 to 10 large images (each loaded into an UIImageView) as subviews. Those images are aligned next to each other, so that they compose a real long horizontal image. This view is put into an UIScrollView, so that the user can scroll along this long horizontal image.</p> <p>Loading all those images (from the web) takes quite some time, so I decided to put that loading code into a NSOperation subclass. Inside the operation's main method each ImageView gets added to the container view.</p> <p>The view is hidden during this process and instead there is a small rotating image (pretty much like an UIActivityIndicatorView). Here is some code:</p> <p>CategoryViewController.m</p> <pre><code>- (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&lt;UIScrollViewDelegate&gt;)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]; } </code></pre> <p>main method of LoadBackgroundImagesOperation.m</p> <pre><code>- (void)main { int left = 0; int width, height; int i; for(i = 0; i &lt; 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]; } </code></pre> <p>When the operation is finished I hide the rotating image and show the view, which contains the large images.</p> <p>(back in CategoryViewController.m again)</p> <pre><code>- (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; } </code></pre> <p>The problem is that it takes around 2 seconds for the simulator and up to 5 seconds on the real device untill the images are actually visible after calling <code>backgroundView.hidden = NO</code></p> <p>I would just continue showing the activity indicator during that time, but I don't know how to detect that <code>backgroundview</code> did appear in order to hide the indicator again.</p> <p>I tried to put <code>backgroundview</code> in its own UIViewController and notify my parent view controller when viewDidAppear is called, but that doesn't work. (I read that in nested view controllers I would have to call viewDidAppear manually, but that is not an option, because i don't know when it did appear in the first place).</p> <p>Also, I can't just do the dirty trick and change the order of <code>backgroundView</code> and <code>loadIndicator</code> to hide it, because most of the images have some transparency in them, so the user would still see the indicator.</p> <p>So I really hope, that any of you guys have a suggestion on how to detect when <code>backgroundview</code> is actually visible.</p> <p>Thanks, Chris</p> <p>Oh, and sorry if some of the code is somewhat unrelated to the problem. Just wanted to give you the big picture of what I am doing.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload