views:

1808

answers:

3

When the app is in one view controller, I want to add a view to simulate that data is being loaded when I click my tab bar controller to open another view controller. Example: When I the app is in the recorder-view, I want it to show a loading view (a view with a activity indicator) when I change to the list of recorded files (which can take some time to load). I've tried manipulate this with the viewWillDisappear-event, but I can't get it to work - the view is not being added before after the viewDidAppear-event occurs.

Anyone have any thoughts regarding this? Thanks

+2  A: 

Right now it sounds like you have a UITabBarController That takes up the whole screen. What I would do is put the loading view above the TabBarController and hide it when not necessary. I would create a subclass of loadingViewController in the same xib your tab bar controller came from (or programatically if you desire) and set it to an IBOutlet of the App Delegate.

Something like this:

//In your App Delegate
- (void)applicationDidFinishLaunching:(UIApplication *)application {
    [window addSubview:tabBarController.view];
        loadingView.hidden = YES;
    [window insertSubview:loadingViewController.view aboveSubview:abBarController.view];
        [window makeKeyAndVisible];
}


//In your loading View Controller
- (void) setLoadingViewHidden:(BOOL)hidden {
        self.view.hidden = hidden;
        self.activityIndicator.animating = hidden;
}
Brad Smith
A: 

Thank you for your reply. I tried doing like tou suggested, but I still can't get it to show when I want. I try to set hidden = NO in my viewWillDisappear-event, but it does not show before that view controller disappears and the next one appears

Hans Espen
+1  A: 

The way I've done this in the past is to have a content view which houses either an activity view or the view proper.

In the view controller's nib, instead of adding subviews to the main view, leave it empty and create a new view (such as a table view in the example below) for the view proper.

Also create an activity view (with a threaded progress indicator or somesuch) and a "no results" view.

Then derive your controller class from the something like the following:

//
//  ContainerViewController.h
//

#import <UIKit/UIKit.h>

@interface ContainerViewController : UIViewController
{
    UIView *myContainerView;

    UITableView *myTableView;
    UIView *mySearchActivityView;
    UIView *myZeroResultsView;

    UIView *myCurrentlyShowingView;
}

@property (retain, nonatomic) IBOutlet UIView *containerView;

@property (retain, nonatomic) IBOutlet UITableView *tableView;
@property (retain, nonatomic) IBOutlet UIView *searchActivityView;
@property (retain, nonatomic) IBOutlet UIView *zeroResultsView;

@property (assign) UIView *currentlyShowingView;

@end

//
//  ContainerViewController.m
//

#import "ContainerViewController.h"

@implementation ContainerViewController

@synthesize containerView = myContainerView;

@synthesize tableView = myTableView;
@synthesize searchActivityView = mySearchActivityView;
@synthesize zeroResultsView = myZeroResultsView;

- (void)dealloc
{
    [myContainerView release], myContainerView = nil;
    [myTableView release], myTableView = nil;
    [mySearchActivityView release], mySearchActivityView = nil;
    [myZeroResultsView release], myZeroResultsView = nil;

    myCurrentlyShowingView = nil;

    [super dealloc];
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.currentlyShowingView = mySearchActivityView;
    mySearchActivityView.backgroundColor = [UIColor clearColor];
    myZeroResultsView.backgroundColor = [UIColor clearColor];
}

- (void)setCurrentlyShowingView:(UIView *)view
{
    [myCurrentlyShowingView removeFromSuperview];
    CGRect frame = view.frame;
    frame.size = myContainerView.frame.size;
    view.frame = frame;
    [myContainerView addSubview:view];
    myCurrentlyShowingView = view;
    if (view == myTableView)
        [myTableView reloadData];
}

- (UIView *)currentlyShowingView
{
    return myCurrentlyShowingView;
}

@end

And in the -viewDidLoad method of the derived class, set off the (asynchronous) query:

- (void)viewDidLoad
{
    [super viewDidLoad];

    myQueryLoader = [[QueryLoader alloc] initWithQuery:@"whatever" delegate:self];
    self.currentlyShowingView = mySearchActivityView;
}

and in the delegate callback:

- (void)queryLoader:(QueryLoader *)queryLoader didEndWithResults:(id)results error:(NSError *)error
{
    myItems = [results retain];

    if (myItems)
        self.currentlyShowingView = myTableView;
    else
        self.currentlyShowingView = myZeroResultsView;
}

Hope this helps!

hatfinch
Thank you for a detailed response! this looks like an elegant solution, I will try this code over the weekend =)
Hans Espen