3
votes

I want to load some data when a button is pressed and show a "loading view" as a subview of my current view while it's loading.

So I want to start loading only after the subview did appear. If not my UI gets stuck without a notice (and the subview only shows after the loading is done).

Is there a way to use something like viewDidAppearfor subviews?

Doing the work right after the addSubview: like this doesn't work:

- (void)doSomeWorkAndShowLoadingView
{
    UIView *loadingView = [[[UIView alloc] initWithFrame:self.view.frame] autorelease];
    loadingView.backgroundColor = [UIColor redColor];
    [self.view addSubview:loadingView];
    [self doSomeWork];
    [loadingView removeFromSuperview];
}
- (void)doSomeWork
{ 
    sleep(5);
}

(I don't want to do the loading on a new thread, because is's CoreData i'm working on, which is't thread safe).

Thank You!

2

2 Answers

2
votes

I found a solution:

Adding the subview with an animation I could use - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag to call something like subviewDidAppear of the delegate of the subview.

In subclass of UIView:

#define KEY_SHOW_VIEW @"_ShowLoadingView_"
#define KEY_HIDE_VIEW @"_HideLoadingView_"
- (void)addToSuperview:(UIView *)theSuperview
{

    [theSuperview addSubview:self];   

    CATransition *animation = [CATransition animation];
    [animation setDuration:0.2];
    [animation setType:kCATransitionFade];
    [animation setDelegate:self];
    [animation setRemovedOnCompletion:NO];
    [animation setValue:KEY_SHOW_VIEW forKey:@"animation_key"];
    [[theSuperview layer] addAnimation:animation forKey:nil];

}

- (void)removeFromSuperview
{
    CATransition *animation = [CATransition animation];
    [animation setDuration:0.2];
    [animation setType:kCATransitionFade];
    [animation setDelegate:self];
    [animation setRemovedOnCompletion:NO];
    [animation setValue:KEY_HIDE_VIEW forKey:@"animation_key"];
    [[self.superview layer] addAnimation:animation forKey:nil]; 

    [super removeFromSuperview];
}

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{    
    NSString* key = [anim valueForKey:@"animation_key"];
    if ([key isEqualToString:KEY_SHOW_VIEW]) {
        if (self.delegate) {
            if ([self.delegate respondsToSelector:@selector(loadingViewDidAppear:)]) {
                [self.delegate loadingViewDidAppear:self];
            } 
        }
    } else if ([key isEqualToString:KEY_HIDE_VIEW]){
        [self removeFromSuperview];
    }
}

This got me the results I was looking for.

Thanks again for your help!

1
votes

You should either be able to simply start your loading directly after calling [parentView addSubview:loadingView] or in your loading view (assuming it is subclassed) override didMoveToSuperview like so:

- (void)didMoveToSuperview {
    // [self superview] has changed, start loading now...
}