Wrong region when map view is subclassed - ios

If I subclass mkmapview I am unable to programmatically zoom in to the full extent. If I do not subclass, zooming works as expected.
My mkmapview subclass:
MyMapView.h
#import <MapKit/MapKit.h>
#interface MyMapView : MKMapView {
}
-(id)initWithLocation:(NSInteger)location;
#end
MyMapView.m
#import "MyMapView.h"
#implementation MyMapView
-(id)initWithLocation:(NSInteger)location; {
self = [super init];
if (self) {
}
return self;
}
my viewcontroller.m:
MyMapView *theMap = [[MyMapView alloc] initWithLocation:0];
theMap.frame = CGRectMake(0, 0, 320, 320);
[self.view addSubview:theMap];
float lat = 33.78;
float lon = -84.56;
CLLocationCoordinate2D newCenter = CLLocationCoordinate2DMake(lat, lon);
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance (newCenter, 10, 10);
[theMap setRegion:region animated:YES];
The resulting map view region is zoomed out much farther than I want. I know the 10 meters is probably tighter than can fit, but I expect the map to be zoomed in as tightly as it can. After the map finishes zooming, I can still manually zoom in 2 more levels.
I could fix the whole thing by including all the code in my main view controller, but I want to abstract the map a bit and keep my viewcontroller.m file cleaner and smaller.
What stupid mistake am I doing?

According to Apple's documentation, you should not subclass MKMapView.
Although you should not subclass the MKMapView class itself, you can get information about the map view’s behavior by providing a delegate object.

Related

google map marker hide inside the uisearchbar and not display in center of the map

i am using google map api for display the location and search bar for search the location but when the GSMMarker display it snippet window hide inside the uisearchbar so any own please help me.
-(void) setupMarkerOnMap:(CLLocation *)loc PlaceName:(NSString *) strCityName
{
[[self getGoogleMap] clear];
[self getNextButton].enabled = YES;
placeMarker = [GMSMarker markerWithPosition:loc.coordinate];
placeMarker.map = [self getGoogleMap];
[placeMarker setTappable:NO];
placeMarker.snippet = strCityName;
placeMarker.icon = [UIImage imageNamed:#"LocationMarker.png"];
GMSCameraUpdate *updateCamera = [GMSCameraUpdate setTarget:placeMarker.position zoom:10.0];
[[self getGoogleMap] animateWithCameraUpdate:updateCamera];
[[self getGoogleMap] setSelectedMarker:placeMarker];
}
these my code snippet for marker add in google map and i attached image which can help you.
anyone can help me.
Thanks
First of all, Make sure that your Google map does not stack together with the search bar. Then you can use delegate to help you move the animate the marker's position inside the Google Map when you tap on any of the marker. Example code:-
Implement the Google Map Delegate
#interface YourViewController ()<GMSMapViewDelegate>
#property (weak, nonatomic) IBOutlet GMSMapView *mapView;
#end
Set the mapView Delegate to the current view controller
- (void)viewDidLoad
{
[super viewDidLoad];
self.mapView.delegate = self;
}
Whenever a marker is tapped, the
-(BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker{
[mapView animateToLocation:marker.position];
return YES;
}
If you have everything setup correctly and the map is big enough, info window should be displayed nicely inside the map.

Issue with sending data from one view to another.

I am trying to transfer a users location from a screen where I allow the user to take a picture to another view where I have a map. The purpose of this is to tag the image location on the map and have that be related with the image. The current code I have for launching the ability to take an image is as follows:
- (IBAction)takePhoto:(UIButton *)sender {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentViewController:picker animated:YES completion: NULL];
}
-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
// Pin location as annotation on map
NSString *dateString = [NSDateFormatter localizedStringFromDate:[NSDate date]
dateStyle:NSDateFormatterShortStyle
timeStyle:NSDateFormatterFullStyle];
MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
MKUserLocation *userLocation = [[MKUserLocation alloc] init];
MKMapView *mapView = [[MKMapView alloc] init];
point.coordinate = userLocation.coordinate;
point.title = #"Picture Entry";
point.subtitle = dateString;
[mapView addAnnotation:point];
// Close camera and go back to home screen
[self dismissModalViewControllerAnimated:YES];
}
I'm new to iOS programming and I'm not sure how to pass the location back to my mapView, and I believe in this code I'm just initializing a new map to save the annotation to, and thats not what I want obviously.
MapViewController.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface MapViewController : UIViewController <MKMapViewDelegate>
#property (strong, nonatomic) IBOutlet MKMapView *mapView;
#end
MapViewController.m
#import "MapViewController.h"
#interface MapViewController ()
#end
#implementation MapViewController
#synthesize mapView;
- (void)viewDidLoad
{
// Get user location
mapView.showsUserLocation = YES;
self.mapView.delegate = self;
}
// Update map based on user location and zoom to area
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:
(MKUserLocation *)userLocation
{
mapView.centerCoordinate = userLocation.location.coordinate;
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 800, 800);
[self.mapView setRegion:[self.mapView regionThatFits:region] animated:YES];
}
#end
This is what I have for now, and I'm at a loss for how to handle this.
I believe in this code I'm just initializing a new map to save the annotation to, and thats not what I want obviously.
You're right -- you're creating a new map and adding the annotation to that object. (Also, you're not creating the map view correctly -- you should use -initWithFrame: because that's a designated initializer for views.)
You should rethink your approach. What you seem to be trying to do is to modify the map view of one view controller (your MapViewController) from a different view controller (assuming that the image picker delegate is some view controller other than MapViewController). A view controller should be in charge of its own views but shouldn't mess with the views of another view controller. Also, adding the annotation that way means that you're effectively storing the location in the map view, and you should avoid using views to store data.
Instead, think about where you should really be saving your data. The M in MVC is for model, i.e. that part of your app that manages the data. As you can see in the acronym, it should be separate from your view(s) and from your controller(s). The model is something that your various view controllers can all use to get the information they need, and having one makes your app simpler because you don't have to worry as much about sending data back and forth between view controllers. The model doesn't have to be anything terribly complicated -- for very simple apps that mainly manage a list of items, even an plain old NSArray or NSSet could serve as a data model. Give each view controller that needs it a reference to the model, or to part of the model.
With that in mind, the right way to fix your app is to have some sort of data model. The image picker delegate should update the map by adding information to the model. The map view controller should be in charge of adding annotations to the map view, and it can do that based on the information in the model.

MKMapView location won't update

After posting on Apple's iOS Devs forums with no answer, I'm trying to see if anyone's got any experience with such issue.
I'm using xcode for iOS 7.
MapView won't update. I'm quite sure the problem's within the simulator, though I'm not sure how to check it. I'd love to take this project on a real device but my iOS 7 device's still in store.
I created a MKMapView nested under a View (nested under a ViewController) -> Added CoreLocation and MapKit into Frameworks -> Connected the MKMapView to the right property mapView.
My files look like this:
MapScanViewController.h:
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface MapScanViewController : UIViewController<MKMapViewDelegate>
// I was trying to create a label and print the
// userLocation description into the label - but none worked
#property (nonatomic,retain) IBOutlet UILabel *myLabel;
#property (nonatomic,strong) IBOutlet MKMapView *mapView;
#end
And MapScanViewController.m :
#import "MapScanViewController.h"
#implementation MapScanViewController
- (void)viewDidLoad
{
[super viewDidLoad];
_mapView.delegate = self;
}
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 800, 800);
[_mapView setRegion:[_mapView regionThatFits:region] animated:YES];
// Label idea did not work eiter
[_myLabel setText:[userLocation description]];
}
#end
When I try to change location to Apple's Infinite loop, the map stays still like nothing's changing at all. Also tried to use bicycle ride and running but nothing happened.
I tried to reset the iOS Simulator few times which did not help at all and of course tried to manually set the location from within xcode it-self.
Tried to add/force this (which did not help either):
if (_mapView.showsUserLocation)
{
_mapView.showsUserLocation = NO;
_mapView.showsUserLocation = YES;
}
None worked for me. MapView just wont respond.
I verified the map view
// Meters-Miles convertion
#define METERS_PER_MILE 1609.344
// Just wanted to check if MapView's dead or not - worked- it took me to see (39.28..., -76.58...)
- (void)viewWillAppear:(BOOL)animated {
// 1
CLLocationCoordinate2D zoomLocation;
zoomLocation.latitude = 39.281516;
zoomLocation.longitude= -76.580806;
// 2
MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(zoomLocation, 0.5*METERS_PER_MILE, 0.5*METERS_PER_MILE);
// 3
[_mapView setRegion:viewRegion animated:YES];
}
you have to call _mapView.showsUserLocation = YES; before you get anything from the map.
That call will for prompt the user for access to location services.
As Daij-Djan said Try like this
- (void)viewDidLoad
{
_mapView.showsUserLocation = YES;
}

viewForAnnotation Is Not Getting Called

Having scanned all the similar problems and tried all possible solutions, I still can't find the solution to my case. I tried to put multiple pins on my MapView but it seems that my pin can't be added normally. I started a NSTimer in my viewDidLoad method so that every 5 seconds, some updated pins will be put on Map. I added debugging information and found the problem was the that the method viewForAnnotation is not getting called.
(I've already set the delegate by calling [_map setDelegate:self])
My code is as following:
- (void)viewDidLoad
{
[super viewDidLoad];
_map = [[MKMapView alloc] initWithFrame:[[self view] frame]];
[_map setDelegate:self];
CLLocationCoordinate2D startLocation;
startLocation.latitude = [startLat floatValue];
startLocation.longitude = [startLong floatValue];
MKCoordinateSpan span = MKCoordinateSpanMake(0.002, 0.002);
MKCoordinateRegion region = MKCoordinateRegionMake(startLocation, span);
[_map setRegion:region];
[[self view] addSubview:_map];
[self getPlacesForLocation:[_map centerCoordinate]];
NSTimer *currentTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:#selector(theActionMethod:) userInfo:nil repeats:YES];
[currentTimer fire];
}
The getPlacesForLocationMethod:
-(void)getPlacesForLocation:(CLLocationCoordinate2D)location
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^
{
/* get data from the website
** get the geo information and put them in the MapPin struct
*/
[self putPinsOnMap];
}
}
putPinsOnMap:
-(void)putPinsOnMap
{
for(Pinfo *iter in [_PinfoArray copy])
{
MapPin *pin = [[MapPin alloc] init];
[pin setTitle:[iter from_user_name]];
[pin setSubtitle:[iter text]];
[pin setCoordinate:[iter location]];
//NSLog(#"The coordinate is %f %f", [pin coordinate].latitude, [pin coordinate].longitude);
[_map addAnnotation:pin];
/****************************************/
NSLog(#"Try to put the pin on Map");
/****************************************/
}
}
And here is the content of my MapPin.h:
#interface MapPin : NSObject<MKAnnotation>
#property (nonatomic, copy) NSString *title, *subtitle;
#property (nonatomic) CLLocationCoordinate2D coordinate;
#end
If I stay in place, then every time the (void)putPinsOnMap gets called, it prints "Try to put pin on Map" but the viewForAnnotation method is not getting called (I also added debugging info there but none of them are printed). Only a few times, the method viewForAnnotation sometimes will be called if I zoom out to a great extent.
You say you added debugging info to viewForAnnotation, but you haven't subclassed MKMapView to override the viewForAnnotation method (or at least, you are allocating an MKMapView, not any subclass). I think you are looking for the delegate method:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation;
and if you implement that method in your view controller (which you are making the delegate of the MKMapView) you might get useful information.
If mapView:viewForAnnotation: is still not called except when you zoom way out then you have probably placed your annotations incorrectly and they're just way out on some other part of the globe than the one you have initially on screen.

How to ensure display of overlays in iOS MapKit

I've looked at several StackOverflow posts and Apple documentation on how to implement overlays in MKMapView. For me, I'm interested specifically in displaying MKPolygon objects on my map. I've found that fundamentally, the process boils down to the following:
Link to MapKit and CoreLocation frameworks
Make an outlet to an MKMapKit object and declare view controller as delegate
Declare a CLLocationCoordinate2D array containing the points of a polygon and create an MKPolygon object with the class method polygonWithCoordinates:count:
Call addOverlay: of map and pass the newly created MKPolygon object as the parameter
Implement (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id)overlay
Later on, I'll likely be having to display 20-30 polygons at a given time on the map. However, in my exploration of how to display overlays (hardcoding test examples right now, rather than reading in data from a file), I've found that I can get some overlays to appear, but not others. Reading the Location Awareness Programming Guide by Apple, I came across an example of a polygon overlaid above the state of Colorado. That worked. But when I tried to make a polygon that covered Kansas, I couldn't get it to work. It seems that any polygon that I tried to make on my own (Embry-Riddle Aeronautical University polygon and Kansas polygon) won't display, but those that I got online work perfectly. I used Google Earth to create the polygons and then exported them as KML files to get the coordinates.
Code for the implementation of my ViewController is below. Just trying to find out what I may be unintentionally doing wrong to create this problem. Thanks in advance for help.
#import "ViewController.h"
#import <CoreLocation/CoreLocation.h>
#interface ViewController ()
#end
#implementation ViewController
#synthesize mapView;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// Array of coordinates for polygon covering state of Colorado ... DISPLAYS PERFECTLY
CLLocationCoordinate2D points[4];
points[0] = CLLocationCoordinate2DMake(41.000512, -109.050116);
points[1] = CLLocationCoordinate2DMake(36.99892, -109.045267);
points[2] = CLLocationCoordinate2DMake(36.993076, -102.041981);
points[3] = CLLocationCoordinate2DMake(41.002371, -102.052066);
MKPolygon *polygon = [MKPolygon polygonWithCoordinates:points count:4];
[mapView addOverlay:polygon];
[polygon release];
// Array of coordinates for polygon covering state of Kansas ... DOESN'T DISPLAY
CLLocationCoordinate2D kansasPoints[9];
kansasPoints[0] = CLLocationCoordinate2DMake(-102.0595440241806, 39.99774930940907);
kansasPoints[1] = CLLocationCoordinate2DMake(-102.0424467175215, 36.99846609483674);
kansasPoints[2] = CLLocationCoordinate2DMake(-94.62550551403953, 36.98936020770036);
kansasPoints[3] = CLLocationCoordinate2DMake(-94.58798745384412, 39.11683771419185);
kansasPoints[4] = CLLocationCoordinate2DMake(-94.79955391183, 39.21290793052091);
kansasPoints[5] = CLLocationCoordinate2DMake(-95.13489191971419, 39.51613476830012);
kansasPoints[6] = CLLocationCoordinate2DMake(-94.86553124171813, 39.78380472206268);
kansasPoints[7] = CLLocationCoordinate2DMake(-95.02618283417986, 39.89072859904893);
kansasPoints[8] = CLLocationCoordinate2DMake(-95.31904155494097, 39.99390420513669);
MKPolygon *kansasPolygon = [MKPolygon polygonWithCoordinates:kansasPoints count:9];
[mapView addOverlay:kansasPolygon];
[kansasPolygon release];
// Array of coordinates for polygon covering part of Daytona Beach, FL campus
// of Embry-Riddle Aeronautical University... DOESN'T DISPLAY
CLLocationCoordinate2D erauPoints[7];
erauPoints[0] = CLLocationCoordinate2DMake(-81.05176, 29.18492);
erauPoints[1] = CLLocationCoordinate2DMake(-81.04409, 29.18801);
erauPoints[2] = CLLocationCoordinate2DMake(-81.05166, 29.19293);
erauPoints[3] = CLLocationCoordinate2DMake(-81.05365, 29.19536);
erauPoints[4] = CLLocationCoordinate2DMake(-81.05465, 29.19493);
erauPoints[5] = CLLocationCoordinate2DMake(-81.05376, 29.19323);
erauPoints[6] = CLLocationCoordinate2DMake(-81.05506, 29.19188);
MKPolygon *erauPolygon = [MKPolygon polygonWithCoordinates:erauPoints count:7];
[mapView addOverlay:erauPolygon];
[erauPolygon release];
// Array of coordinates taken from http://www.shawngrimes.me/2011/04/adding-polygon-map-overlays/
// for commuter parking lot at Capitol College in Maryland ... DISPLAYS PERFECTLY
CLLocationCoordinate2D commuterLotCoords[5]={
CLLocationCoordinate2DMake(39.048019,-76.850535),
CLLocationCoordinate2DMake(39.048027,-76.850234),
CLLocationCoordinate2DMake(39.047407,-76.850181),
CLLocationCoordinate2DMake(39.047407,-76.8505),
CLLocationCoordinate2DMake(39.048019,-76.850535)
};
MKPolygon *commuterPoly1 = [MKPolygon polygonWithCoordinates:commuterLotCoords count:5];
[mapView addOverlay:commuterPoly1];
[commuterPoly1 release];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay {
if ([overlay isKindOfClass:[MKPolygon class]]) {
MKPolygonView *polygonView = [[[MKPolygonView alloc] initWithOverlay:overlay] autorelease];
polygonView.fillColor = [[UIColor cyanColor] colorWithAlphaComponent:0.3f];
polygonView.strokeColor = [UIColor redColor];
polygonView.lineWidth = 1.0f;
return polygonView;
}
return nil;
}
#end
It looks like the latitude and longitude parameters of the coordinates for the polygons that don't display are backwards.
For example, this:
kansasPoints[0] = CLLocationCoordinate2DMake(-102.0595440241806, 39.99774930940907);
should be
kansasPoints[0] = CLLocationCoordinate2DMake(39.99774930940907, -102.0595440241806);
Also, you should not be calling release on the MKPolygon objects you are creating using polygonWithCoordinates since they will be autoreleased.

Resources