I have a normal MKMap view with a basic MKAnnoation what i want to accomplish is that my annotation is in the UK and the MKCoordinateSpan is 0.05 but i want the MKMapView start from a view of the whole UK and zoom in to the annotation.
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
/* set here the region from where map will be zooming; */
[self.mapView setRegion:MKCoordinateRegionForMapRect(MKMapRectWorld) animated:NO];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
/* set here your end point of zooming */
CLLocationCoordinate2D zoomLocation;
zoomLocation.latitude = 39.281516;
zoomLocation.longitude= -76.580806;
[self.mapView setCenterCoordinate:zoomLocation animated:YES];
CLLocationDistance locationDistance = [self locationDistance:0.5];
MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(zoomLocation, locationDistance, locationDistance);
[self.mapView setRegion:viewRegion animated:YES];
}
- (CLLocationDistance )locationDistance:(CGFloat )value {
return 1609.344 *value;
}
Related
I have set up a simple MKMapView (it is intended just to display a location on the map and nothing more) within one cell of a section of a CollectionView and am unable to set its region using setRegion. The MKMapViewDelegate is correctly set to the UICollectionViewCell as shown by breakpoints being hit within all the delegate methods.
I first tried to set the region in the View Controller's cellForItemAtIndexPath but I'm guessing this is too early, i.e. before the map is loaded so nothing happens and it loads a default location in the middle of the ocean.
I have tried passing the CLCoordinateLocation2D from the view controller to a CLCoordinateLocation2D in the cell during cellForItemAtIndexPath to set the region within the cell but where is the appropriate place to set the region? In a ViewController it should be done in ViewDidAppear rather than ViewDidLoad or ViewWillAppear so that the map is loaded but I cannot find an equivalent event for a collectionviewcell. awakeFromNib is clearly too soon. I have tried using various mapView delegates such as:
- (void)mapView:(MKMapView *)mapView1
regionWillChangeAnimated:(BOOL)animated
{
MKCoordinateSpan span = {.latitudeDelta = 0.0025, .longitudeDelta = 0.0025};
MKCoordinateRegion adjustedRegion = [mapView1 regionThatFits:MKCoordinateRegionMakeWithDistance(coords, 200, 200)];
[mapView1 setRegion:adjustedRegion animated:YES];
}
which runs but again does not change the region. I have tried
- (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView and
- (void)mapViewWillStartRenderingMap:(MKMapView *)mapView
which seemed the best bets but a breakpoint before and after the setRegion line shows the region is never updated to the region I'm setting it to. The events all should be at a time that the map is fully loaded so why does setRegion simply have no effect??
Cell h file:
#interface BasicsCollectionViewCell : UICollectionViewCell
#property (strong, nonatomic) IBOutlet MKMapView *mapView;
#property (nonatomic) CLLocationCoordinate2D coords;
#end
Cell m file:
#interface BasicsCollectionViewCell() <MKMapViewDelegate>
#end
#implementation BasicsCollectionViewCell
#synthesize mapView;
#synthesize coords;
- (void)mapView:(MKMapView *)mapView1
regionWillChangeAnimated:(BOOL)animated
{
MKCoordinateSpan span = {.latitudeDelta = 0.0025, .longitudeDelta = 0.0025};
MKCoordinateRegion adjustedRegion = [mapView1 regionThatFits:MKCoordinateRegionMakeWithDistance(coords, 200, 200)];
[mapView1 setRegion:adjustedRegion animated:YES];
}
And the relevant part of cellForItemAtIndexPath:
cell0 = (BasicsCollectionViewCell*)[collectionView dequeueReusableCellWithReuseIdentifier:#"BasicsCell" forIndexPath:indexPath];
CLLocationCoordinate2D coord = {.latitude = self.latitude, .longitude = self.longitude};
[cell0 setCoords:coord];
cell0.mapView.delegate = cell0;
MKCoordinateSpan span = {.latitudeDelta = 0.0025, .longitudeDelta = 0.0025};
MKCoordinateRegion adjustedRegion = [cell0.mapView regionThatFits:MKCoordinateRegionMakeWithDistance(coord, 200, 200)];
[cell0.mapView setRegion:adjustedRegion animated:YES];
return cell0;
EDIT:
If I put breakpoints in the following code before and after the setRegion line at the asterixed points...
- (void)mapViewWillStartRenderingMap:(MKMapView *)mapView
{
MKCoordinateSpan span = {.latitudeDelta = 0.0025, .longitudeDelta = 0.0025};
MKCoordinateRegion adjustedRegion = [mapView regionThatFits:MKCoordinateRegionMakeWithDistance(coords, 200, 200)];
*****[mapView setRegion:adjustedRegion animated:YES];
*****}
then the debugger gives the following at the first breakpoint:
po self.mapView.region
{
(latitude = -41.508575000000008, longitude = 174.19921900000011)
(latitudeDelta = 13.733789001832008, longitudeDelta = 59.305518116231042)
}
And the same at the breakpoint immediately after:
po self.mapView.region
{
(latitude = -41.508575000000008, longitude = 174.19921900000011)
(latitudeDelta = 13.733789001832008, longitudeDelta = 59.305518116231042)
}
While at both breakpoints, the following is the (correct) value of adjustedRegion:
po adjustedRegion
{
(latitude = -0.13506928037132482, longitude = 51.518398284912109)
(latitudeDelta = 0.0018087389042361623, longitudeDelta = 0.0058458603824931288)
}
So it is simply that either setRegion is being ignored for some reason or it’s overridden by something else. Any ideas which?
I have faced similar one, where map region was not changed. So I manually called mapView delegate method
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated;
in - (void) viewDidAppear:(BOOL)animated of view controller.
- (void) viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
// Manually called delegate method to forcefully set region.
[self mapView:self.mapView regionDidChangeAnimated:YES];
}
In your case call this method right after when you set map region. From your above code for example in cellForItemAtIndexPath method. For example:
cell0 = (BasicsCollectionViewCell*)[collectionView dequeueReusableCellWithReuseIdentifier:#"BasicsCell" forIndexPath:indexPath];
CLLocationCoordinate2D coord = {.latitude = self.latitude, .longitude = self.longitude};
[cell0 setCoords:coord];
cell0.mapView.delegate = cell0;
MKCoordinateSpan span = {.latitudeDelta = 0.0025, .longitudeDelta = 0.0025};
MKCoordinateRegion adjustedRegion = [cell0.mapView regionThatFits:MKCoordinateRegionMakeWithDistance(coord, 200, 200)];
[cell0.mapView setRegion:adjustedRegion animated:YES];
[cell0.mapView setRegion:adjustedRegion animated:YES];
// Force call of delegate method
[self mapView:cell0.mapView regionDidChangeAnimated:YES];
return cell0;
Note:
Don't forgot to override regionDidChangeAnimated method in view controller.
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
}
The same method is working fine in ios 6
I am using didUpdateToLocation method and its implemented as follows:-
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)Location fromLocation:(CLLocation *)oldLocation
{
if(appDelegate->mapView )
{
if(Span)
{
[appDelegate->mapView setRegion:MKCoordinateRegionMake(Location.coordinate, MKCoordinateSpanMake(0.01f, 0.01f)) animated:YES];
Span = NO;
}
else
{
[appDelegate->mapView setCenterCoordinate:Location.coordinate animated:YES];
}
}
}
Please suggest what should be done so that the user's location should also be tracked and user should also be able to zoom in and out on the map.The map should also center itself around the current GPS location.
i use this to zoom the the users location when the map is loaded.
- (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView {
NSLog(#"mapViewDidFinishLoadingMap");
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self zoomMapView:mapView ToUserLocation:mapView.userLocation.coordinate];
}); }
-(void)zoomMapView:(MKMapView*)mapView ToUserLocation:(CLLocationCoordinate2D)coordinate {
if (!isZoomed) {
isZoomed=TRUE;
MKCoordinateRegion region = mapView.region;
MKCoordinateSpan span;
region.center = coordinate;
span.latitudeDelta = 0.02;
span.longitudeDelta = 0.02;
region.span=span;
[mapView setMapType:MKMapTypeStandard];
[mapView setZoomEnabled:YES];
[mapView setScrollEnabled:YES];
[mapView setShowsUserLocation:YES];
[mapView setRegion:region animated:YES];
} }
you can call the -(void)zoomMapView:(MKMapView*)mapView ToUserLocation:(CLLocationCoordinate2D)coordinate method whenever you want to zoom the the users current location.
I am new in iOS apps development and I want to put a Map in My application with a pushpin on an exact location using its latitude and longitude. I add the Map but the problem is it always appear with its initial position an the push pin doesn't appear (It is on the map but you need to change the position to see it ) . Like this figures shows :
Initial Position
2.- After I moved the map's position
What I want is to show the position of the pushpin as a default location and with a zoom .
This is a sample of My Code :
- (void)viewDidLoad
{
[super viewDidLoad];
CLLocationCoordinate2D myCoordinate = {20.5, -7.06}; //AS an Example
MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
point.coordinate = myCoordinate;
//Drop pin on map
[self.mapView addAnnotation:point];
//Region with Zoom
-(void)viewWillAppear:(BOOL)animated {
CLLocationCoordinate2D zoomLocation;
zoomLocation.latitude = 20.5;
zoomLocation.longitude= -7.6;
MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(zoomLocation, 0.5*METERS_PER_MILE, 0.5*METERS_PER_MILE);
[self.mapView setRegion:viewRegion animated:YES];
}
I used this code but still the same thing it always display the initial position (Figure 1)
Thank You .
(void)viewDidLoad
{
[super viewDidLoad];
MapAnnotation *ann = [[MapAnnotation alloc] init];
MKCoordinateRegion region;
region.center.latitude = 31.504679;
region.center.longitude = 74.247429;
region.span.latitudeDelta = 0.01;
region.span.longitudeDelta = 0.01;
[mapView setRegion:region animated:YES];
ann.title = #"Digital Net";
ann.subtitle = #"Office";
ann.coordinate = region.center;
[mapView addAnnotation:ann];
}
(MKAnnotationView *) mapView:(MKMapView *)mpView viewForAnnotation:(id)annotation {
MKPinAnnotationView *pinView = nil;
if(annotation != mapView.userLocation) {
static NSString *defaultID = #"myLocation";
pinView = (MKPinAnnotationView *)[mpView dequeueReusableAnnotationViewWithIdentifier:defaultID];
if(pinView == nil) {
pinView = [[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:defaultID];
pinView.pinColor = MKPinAnnotationColorGreen;
pinView.canShowCallout = YES;
pinView.animatesDrop = YES;
}
}
return pinView;
}
I have done something like that and it was working fine
Im using MKMapView to get the users location and when the view loads it shows the whole world view. Is there anyway that I can set a zoom level so that the users don't have to keep zooming in always to get the city view or street view...It would be a great help. I've posted my code below for reference...
- (void)viewDidLoad
{
[super viewDidLoad];
[ self.mapView.delegate self];
[self.mapView setShowsUserLocation:YES];
// Do any additional setup after loading the view, typically from a nib.
}
-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
CLLocationCoordinate2D loc = [userLocation coordinate];
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(loc, 500, 500);
[self.mapView setRegion:region animated:YES];
}
- (void)viewDidUnload {
[super viewDidUnload];
[_mapView setShowsUserLocation:NO];
}
The code you've posted should work for the most part except for this critical line in viewDidLoad:
[ self.mapView.delegate self];
Essentially, this line does nothing.
It is not setting the map view's delegate property (which is what I assume it is supposed to do).
What it is actually doing is calling self on the delegate property.
The map view's delegate is not getting set (it stays nil) and so the didUpdateUserLocation delegate method never gets called and so the map is not zooming to the user's location.
The line should be this:
[self.mapView setDelegate:self];
or even simpler:
self.mapView.delegate = self;
Note that in iOS 5 or later, you can just set userTrackingMode and the map view will automatically zoom to and follow the user's location so you don't have to do it manually.
Also note that since iOS 6, viewDidUnload is deprecated and is not even called by the OS. You probably want to move the disabling of showsUserLocation to viewWillDisappear (and move the enabling to viewWillAppear).
Try this May be Help full for you
MKCoordinateRegion startupRegion;
startupRegion.center = CLLocationCoordinate2DMake(26.0000, 75.00);
startupRegion.span = MKCoordinateSpanMake(0.5, 0.597129);
[mapViewObj setRegion:startupRegion animated:YES];
here 26.0000 and 75.00 is user location and MKCoordinateSpanMake is zoom level. It's increasing your zoom as you wish.
Try this, In ViewDidLoad
CLLocationCoordinate2D zoomLocation;
zoomLocation.latitude = 39.281516; // your latitude value
zoomLocation.longitude= -76.580806; // your longitude value
MKCoordinateRegion region;
MKCoordinateSpan span;
span.latitudeDelta=0.18; // change as per your zoom level
span.longitudeDelta=0.18;
region.span=span;
region.center= zoomLocation;
[self.mapView setRegion:region animated:TRUE];
[self.mapView regionThatFits:region];
set MKCoordinateRegion and change region span according to your requirement
MKCoordinateRegion region;
CLLocation* currentLocation = (CLLocation*)from ; // current location
if(currentLocation.coordinate.latitude > maxLat)
maxLat = currentLocation.coordinate.latitude;
if(currentLocation.coordinate.latitude < minLat)
minLat = currentLocation.coordinate.latitude;
if(currentLocation.coordinate.longitude > maxLon)
maxLon = currentLocation.coordinate.longitude;
if(currentLocation.coordinate.longitude < minLon)
minLon = currentLocation.coordinate.longitude;
region.center.latitude = (maxLat + minLat) / 2;
region.center.longitude = (maxLon + minLon) / 2;
region.span.latitudeDelta = 0.4; // change as per required zoom level
region.span.longitudeDelta = 0.4; // change as per required zoom level
// input that region and set map area as below 30000
_mapView.region =MKCoordinateRegionMakeWithDistance(currentLocation.coordinate,30000, 30000);
[_mapView setRegion:region animated:YES];
[_mapView regionThatFits:region];
[_mapView reloadInputViews];
// center your map at Current location
_mapView.centerCoordinate = _mapView.userLocation.location.coordinate;
// To get current location use CLLocationManagerDelegate
#interface GetCurrentLocation : NSObject<CLLocationManagerDelegate>
#property(nonatomic,strong)CLLocationManager *_locationManager;
-(void)getLocation;
#end
-(void)getLocation{
_locationManager = [[CLLocationManager alloc] init];
[_locationManager setDelegate:self];
[_locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
_locationManager.distanceFilter = kCLDistanceFilterNone;
[_locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation// you can get current location here
{
CLLocationCoordinate2D coord;
coord.latitude = newLocation.coordinate.latitude;
coord.longitude = newLocation.coordinate.longitude;
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
// NSLog(#"locationManager:%# didFailWithError:%#", manager, error);
}
-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
MKCoordinateRegion mapRegion;
mapRegion.center = mapView.userLocation.coordinate;
mapRegion.span.latitudeDelta = 0.3;
mapRegion.span.longitudeDelta = 0.3;
[mapView setRegion:mapRegion animated: YES];
}
I have MKMapView which have UserTrackingMode = MKUserTrackingModeFollow,
and I have adding a circle overlay to show a region of the certain diameter at user location.
Also user can change the diameter of the region so I want to scale the map to insure whole region/circle is shown on that portion of the map.
The problem I have now is that scaling the map number of times by setting region results in incorrect user location annotation - it is moved from the correct location.
I cannot understand why is that happens, I see in the debugger that the mapView.userLocation property have correct coordinates.
But once new update is happens or I move the map manually - the annotation jumps to the correct place.
This is the code:
- (void)addCircleWithRadius:(double)radius andCoordinate:(CLLocationCoordinate2D)coordinate
{
_regionCircle = [MKCircle circleWithCenterCoordinate:coordinate radius:radius];
[_regionCircle setTitle:#"Region"];
MKCoordinateRegion region;
region.center.latitude = coordinate.latitude;
region.center.longitude = coordinate.longitude;
region.span.latitudeDelta = 0.00002 * _regionCircle.radius;
region.span.longitudeDelta = 0.00002 * _regionCircle.radius;
MKCoordinateRegion adjustedRegion = [self.mapView regionThatFits: region];
[self.mapView setRegion:adjustedRegion animated:TRUE];
_circleView = nil;
[self.mapView addOverlay:_regionCircle];
}
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
{
if(!_circleView)
{
_circleView = [[MKCircleView alloc] initWithCircle:overlay];
_circleView.strokeColor = [UIColor blueColor];;
_circleView.fillColor = [UIColor blueColor];
_circleView.alpha = 0.25;
_circleView.lineWidth = 2.0;
}
return _circleView;
}
- (IBAction)regionSliderValueChanged:(id)sender
{
[self updateRadiusCircle];
}
- (void) updateRadiusCircle
{
[self.mapView removeOverlays:self.mapView.overlays];
CLLocationCoordinate2D myCoordinate = {_currentLocation.coordinate.latitude, _currentLocation.coordinate.longitude};
[self addCircleWithRadius:self.radiusSlider.value andCoordinate:myCoordinate];
}
I have published the video on YouTube to better understand the issue.
https://www.youtube.com/watch?v=474gdjkGwJA