eabraham
eabraham

Reputation: 4164

Trying to Preload Google Maps View

I have a Google Map View in a view controller inside of a navigation controller that is on a tabbar controller. Everything works as it should but the load times on the map range from 5-10 seconds when I initially tap on the Map tab.

storyboard-layout

I've come across several StackOverflow posts which list the following method of preloading a tab:

for (UIViewController *viewController in self.tabBarController.viewControllers)
{
    [viewController view];
}

I've modified it to my particular implementation.

for (UIViewController *viewController in self.tabBarController.viewControllers)
{
    UINavigationController *navCon = (UINavigationController*)viewController;
    for (UIViewController *vc in navCon.viewControllers) {
        if ([[NSString stringWithFormat:@"%@",vc.class]  isEqual: @"MapViewController"]){
            MapViewController *mv = (MapViewController*) vc;
            [mv view];
        }

    }
}

Unfortunately, neither implementation preloads the map tab.

Specs

Edit ViewDidLoad on the MapViewController.m

- (void)viewDidLoad
{
    [super viewDidLoad];
    mapView_ = [GMSMapView mapWithFrame:self.view.bounds camera:nil];
    mapView_.delegate = self;
    AppDelegate *appDelegate=(AppDelegate *)[UIApplication sharedApplication].delegate;
    CLLocationCoordinate2D loc=appDelegate.locationManager.location.coordinate;

    GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:loc.latitude
                                                            longitude:loc.longitude
                                                                 zoom:12];
    [mapView_ setCamera:camera];
    mapView_.myLocationEnabled=YES;
    mapView_.settings.myLocationButton = YES;
    self.view = mapView_;
}

Upvotes: 2

Views: 662

Answers (2)

Fattie
Fattie

Reputation: 12278

I'd suggest just using a container view (long how-to ) which is very easy; it will then reliably work independently. If you wish, simply move it offscreen while it is loading (perhaps slide it in afterwards).

Note that inside the container view, say the "parent" is of class Boss,

@implementation SomeContaineredView
-(void)allTheDataLoaded
    {
    [(Boss*)self.parentViewController someMethodInBoss];
    }
@end

it's that easy to talk to the parent class.


NOTE - if you need to communicate from the parent to the containered view, it's very easy if you know the "silly trick" that Apple makes you do .. https://stackoverflow.com/a/15706092/294884

It's a bit whacky, for such a basic operation you do pretty all the time. You do it in prepareForSegue: like this...

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
    {
    if ([segue.identifier isEqualToString:@"containerLogin"])
        self.vcLogin = (LoginVC *)segue.destinationViewController;

    if ([segue.identifier isEqualToString:@"containerStartNew"])
        self.vcStartNew = (StartNewVC *)segue.destinationViewController;

    }

In the example there are two container views. (With identifiers "containerLogin" and "containerStartNew") So, I have two properties (self.vcLogin, self.vcStartNew). That is exactly how you set them.

Note that prepareForSegue is badly named. It should be called something like "Set up which runs when you have an embed segue" I explain this at length here: https://stackoverflow.com/a/24351813/294884

Important! ...

Here's a handy macro!!!

#define seg(A, B, C) if ([segue.identifier isEqualToString:A]) \
                           B = (C *)segue.destinationViewController;

In every project we work on, we use that macro.

Then you can simply write this:

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
    {
    seg(@"cOverlayBuy", self.rockets, Rockets);
    seg(@"cOverlayMainMenu", self.overlayMainMenu, OverlayMainMenu);
    
    seg(@"cSearch", self.search, Search);
    seg(@"cMeeting", self.meeting, Meeting);
    
    seg(@"cMeetings", self.meetings, Meetings);
    seg(@"cBooks", self.bikes, Bikes);
    seg(@"cPeople", self.cars, Cars);
    }

Because, these days, every scene has many container views, every single scene we have, for every client, has that code in the "prepareForSegue" call.

So, once that code runs you can finally "access your container views!"

[self.cars displayColors:@"red"];
self.cars.view.hidden=YES;
[self.meetings calculateNewTimesNow];

...and so on.

Like I say, we use this macro in every project. And pretty much every scene has a few container views these days, so it's in every VC! Hope it helps someone.

Upvotes: 4

Gil Sand
Gil Sand

Reputation: 6038

I think you could instantiate it before that view and then just make it appear when loading that controller. If you can't, maybe you could create it away from the present view and then slide it in when its fully loaded? (and make it appear smooth)

Upvotes: 0

Related Questions