Question

I'm pretty new on iOS development and I'm having the following problem. I need to fill a UITableView with data fetched from a server.

I'm doing this call using AFNetworking. I want to show a "loading view" using SVProgressHUD and I'm doing the following:

-(void) viewDidLoad{
    [super viewDidLoad];
    [SVProgressHUD showWithMaskType:SVProgressHUDMaskTypeGradient];
    [[MyServer sharedManager] fetchFromServerwithCompletionHandler:^(NSArray *elements, BOOL error) {
        _elements = elements;
        [_elementsTableView reloadData];
        [SVProgressHUD dismiss];
    }];
}

I'm getting the correct answer from the server but the progress hud is not being displayed. The call to the server does take some seconds so there is time for the progress hud view to be loaded but nothing happens.

I'm performing the call in the viewDidLoad because I need the call to be made as soon as the view is loaded and I want to call this just once.

If I move this block of code to the viewDidAppear the progress hud loads, but then this method is going to be called every-time the view is shown and I don't want this...

Thanks a lot!

Was it helpful?

Solution

The problem is not that the network call doesn't take place if done in viewDidLoad (because that is the right place to do it), but rather that the attempt to add the SVProgressHUD in viewDidLoad won't work, because this is too early in the process of constructing the view for SVProgressHUD to figure out where to put the HUD.

One simple solution would be to have viewDidLoad defer the invocation of this, to give the UI a chance to get to a state that SVProgressHUD can correctly place itself in the view hierarchy. As silly as it seems, you can just dispatch the code back to the main loop, which gives the UI a chance to catch up:

- (void)viewDidLoad
{
    [super viewDidLoad];

    dispatch_async(dispatch_get_main_queue(), ^{
        [SVProgressHUD showWithMaskType:SVProgressHUDMaskTypeGradient];
        [[MyServer sharedManager] fetchFromServerwithCompletionHandler:^(NSArray *elements, BOOL error) {
            _elements = elements;
            [_elementsTableView reloadData];
            [SVProgressHUD dismiss];
        }];
    });
}

OTHER TIPS

A trick can be use NSUserDefaults to save a value like @"serverAlreadyCalled" and check on viewDidAppear if you called the server before. example:

-(viewDidAppear){
NSUserDefaults* defaults = [NSUserDefaults standardDefaults];

if ([defaults valueForKey:@"serverAlreadyCalled"] == nil) {

[SVProgressHUD showWithMaskType:SVProgressHUDMaskTypeGradient];
[[MyServer sharedManager] fetchFromServerwithCompletionHandler:^(NSArray *elements, BOOL error) {
    _elements = elements;

    [defaults setValue:@"YES" forKey:@"serverAlreadyCalled"];
    [_elementsTableView reloadData];
    [SVProgressHUD dismiss];
}];
}
}

Don't forget to set nil to your key @"serverAlreadyCalled" before your app finishes run.

Maybe it's not the best solution, but can make the trick. Hope it helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top