1

I have my mapView set to a default location every time the view is accessed. Sometimes when you access the view, it will be at the correct spot, although sometimes when you access the view, it will be at the mapView's default location, over the ocean south of Africa. How can I make sure it is in the right spot when the view is accessed.

Here is my code:

-(void)viewDidLoad {

    [super viewDidLoad];

    self.mapView.delegate = self;

    MKCoordinateRegion region = { {0.0, 0.0 }, { 0.0, 0.0 } };
    region.center.latitude = 45.442424;
    region.center.longitude = -122.78;
    region.span.latitudeDelta =  0.60;
    region.span.longitudeDelta =  0.60;
    [mapView setRegion:region animated:YES];
}

This is what loads the annotations:

-(void)initXML {

    NSURL *theURL = [NSURL URLWithString:@"http://www.wccca.com/PITS/"];
    NSData *data = [[NSData alloc] initWithContentsOfURL:theURL];
    xpathParser = [[TFHpple alloc] initWithHTMLData:data];
    NSArray *elements = [xpathParser searchWithXPathQuery:@"//input[@id='hidXMLID']//@value"];
    if (elements.count >= 1) {

        TFHppleElement *element = [elements objectAtIndex:0];
        TFHppleElement *child = [element.children objectAtIndex:0];
        NSString *idValue = [child content];

        NSString *idwithxml = [idValue stringByAppendingFormat:@".xml"];
        NSString *url = @"http://www.wccca.com/PITS/xml/fire_data_";
        NSString *finalurl = [url stringByAppendingString:idwithxml];

        xmlParser = [[XMLParser alloc] loadXMLByURL:finalurl];

        if (xmlParser.calls.count == 0) {

            [self noCallsMessage];
        }
        else {

            [self wcccaAnn];

            NSArray *callsArray = [xmlParser calls];

            for (JointCAD *call in callsArray) {
                NSString *callnumber = [call.callnumber stringByAppendingFormat:@". "];
                NSString *callandnumber = [callnumber stringByAppendingString:call.currentCallType];
                Annotation *ann = [[Annotation alloc] init];
                ann.title = callandnumber;
                ann.subtitle = [call location];
                ann.coordinate = CLLocationCoordinate2DMake([call.latitude doubleValue], [call.longitude doubleValue]);
                [mapView addAnnotation:ann]; }
            }
        }
    }

MKAnnotationView:

-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {

    if ([annotation isKindOfClass:[MKUserLocation class]])
        return nil;

    MKPinAnnotationView *MyPin=[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"current"];
    MyPin.pinColor = MKPinAnnotationColorRed;

    MyPin.draggable = NO;
    MyPin.highlighted = YES;
    MyPin.animatesDrop= YES;
    MyPin.canShowCallout = YES;

    return MyPin;
}
Rob
  • 415,655
  • 72
  • 787
  • 1,044
Jon Erickson
  • 1,876
  • 4
  • 30
  • 73
  • 1
    all ui operations should be performed on main thread – NeverBe Oct 11 '12 at 21:17
  • Where else in this view controller is setRegion being called besides viewDidLoad? –  Oct 12 '12 at 02:50
  • The only other time is when the user presses a button and mapView.showsUserLocation = YES; and the map zooms to the users position. – Jon Erickson Oct 12 '12 at 03:56
  • 1
    That's what @Craig is implying. That other setRegion may be causing the issue. See http://stackoverflow.com/questions/9680576/is-this-a-bug-with-mkmapkitdelegate-mapviewdidupdateuserlocation for possibly why. –  Oct 12 '12 at 11:07
  • I removed the other setRegion so the one above is the only one and it is still not updating when the map loads. It loads to the default (0,0) – Jon Erickson Oct 13 '12 at 19:15

3 Answers3

1

I had the same problem and the following solution (applied to your code) worked for me:

-(void)viewDidLoad {

    [super viewDidLoad];

    self.mapView.delegate = self;

    double delayInSeconds = 0.5;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, int64_t)(delayInSeconds * NSEC_PER_SEC));
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
        MKCoordinateRegion region = { {0.0, 0.0 }, { 0.0, 0.0 } };
        region.center.latitude = 45.442424;
        region.center.longitude = -122.78;
        region.span.latitudeDelta =  0.60;
        region.span.longitudeDelta =  0.60;
        [mapView setRegion:region animated:YES];
    });
}

Basically, you wrap the code that sets the region in a block and call that block after delayInSeconds. I found 0.5 enough of a delay in the simulator, but you should test on your slowest device.

If you don't want to use blocks, you could also wrap the region setting code in a separate method and call something like [self performSelector:@selector(nameOfMethod) withObject:nil afterDelay:0.5f];.

The map will start to load and then quickly animate to the set region. If you don't like this animation then be sure to set the animated parameter to NO.

robfeldmann
  • 151
  • 7
0

You are updating the map on a queue different than the main queue. You are lucky your application is not crashing all over the place. Move the view manipulation to the main thread and see if you keep getting the same problem.

edit: if you really have to use a queue to get that span, just do this with the view:

dispatch_async(dispatch_get_main_queue(), ^{
    [mapView setRegion:region animated:YES]; 
});
J2theC
  • 4,412
  • 1
  • 12
  • 14
  • Still, the map loads to it's default view and not the one I specified. – Jon Erickson Oct 11 '12 at 21:26
  • Did you remove the update to the map view location from a background thread to the main thread? – J2theC Oct 11 '12 at 21:29
  • Yes I did and I also placed it in viewDidLoad and it still is half and half. – Jon Erickson Oct 11 '12 at 21:36
  • The viewDidLoad is only called after loading the viewController that contains the mapView for the first time, or when memory gets low and viewDidUnload gets called. Update your code to reflect your recent changes, and please provide code to show how your application is reacting to some of your MKMapViewDelegate methods. – J2theC Oct 11 '12 at 21:38
0

There is only one point in the code you have above that set the maps the map location (setRegion). If your map is being set to a different location it isn't in the code you have provided.

Craig
  • 8,093
  • 8
  • 42
  • 74
  • It's not that its being moved to a different region, it's that the map ISN'T being moved like it should be from the code above. – Jon Erickson Oct 11 '12 at 23:32