2

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

  • Google Maps SKD 1.7.2
  • iOS SDK 7.1

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_;
}
eabraham
  • 4,094
  • 1
  • 23
  • 29

2 Answers2

4

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.

Community
  • 1
  • 1
Fattie
  • 27,874
  • 70
  • 431
  • 719
  • Have you successfully used container views as a strategy to pre-load views? I'll admit I haven't played around with this. – eabraham Sep 25 '14 at 17:48
  • Absolutely - many times. All we do is complex client-server apps. I usually prefer to just keep them offscreen, and slide them in when ready. – Fattie Sep 25 '14 at 17:51
  • Awesome, I'll give this a try. – eabraham Sep 25 '14 at 17:57
  • I truly hope it helps in some way! Consider too you could fade it in, "uncover it" etc. All very easy w/ container views. Simply call to the parent once the data is loaded or whatever. I edited the answer also – Fattie Sep 25 '14 at 18:00
  • Your answer pointed me in the right direction. I'll do a full write up for future answer seekers. – eabraham Sep 26 '14 at 02:34
  • Hi @eabraham ... I'm really wanting to hear what happened in your solution, please let us know. That's great news. I'm sorry I didn't have much time to write more, I usually write at length! ...eg ... http://stackoverflow.com/a/23403979/294884 – Fattie Sep 26 '14 at 03:43
  • Hey @eabraham - I added an explanation of a super-handy macro we use in dealing with container views. I've never, ever, not needed a link downwards to the container view (to send it data etc); it's quite amazing it is so obscure to get the link! Cheers – Fattie Sep 26 '14 at 03:58
0

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)

Gil Sand
  • 5,802
  • 5
  • 36
  • 78
  • Yes, my question includes code which instantiates the ViewController before making it appear. I confirm that the ViewController has run its ViewDidLoad and that its the same object. Unfortunately, it still takes over 5 seconds to load the google map. – eabraham Sep 25 '14 at 17:33