IOS Development Series-Map and location source code detailed _ios

Source: Internet
Author: User
Tags reserved uikit reverse geocoding

Overview

Now many social, electrical, and group purchase applications have introduced maps and positioning functions, it seems that map function is no longer a map application and navigation applications unique. Indeed, with the map and positioning function does make our life more colorful, greatly changed our way of life. For example, you go to a strange place to find nearby hotels, supermarkets and so on can open the software search around; Similarly, many group buying software can automatically recommend certain items to you based on where you are. In a word, map and location function have been introduced into application development. Today, let's take a look at how iOS maps and locates and develops.

    • Positioning
    • Map

Positioning

To realize the map, navigation function, often need to familiarize themselves with the positioning function, in iOS through the core location framework for positioning operations. The Core location itself can be used alone, and the map development framework Mapkit completely independent, but often map development should be used in conjunction with the positioning framework. The core location includes positioning, geo-coding (including anti-coding) functions.

Positioning function

Positioning is a very common function, such as some map software opened after the user allows software positioning, then open the software will automatically lock to the current position, if the user mobile phone so that the current position will follow the change. To implement this feature, you need to use the Cllocationmanager class in the core loaction to first look at some of the main methods and properties of the class:

Class method Description
+ (BOOL) locationservicesenabled; Whether to enable the positioning service, usually if the user does not enable the locator service to prompt the user to open the location service
+ (clauthorizationstatus) authorizationstatus; Locates the service authorization status, returning the enumeration type:
kclauthorizationstatusnotdetermined: User has not yet made a decision on whether to enable the positioning service
Kclauthorizationstatusrestricted: The user is not authorized to use the location service, the user may not be authorized to prohibit access
Kclauthorizationstatusdenied: User has explicitly prohibited the application using the locate service or the current system Locator service is off
Kclauthorizationstatusauthorizedalways: Application is authorized to use the location service all the time, even if the application is not in use state
Kclauthorizationstatusauthorizedwheninuse: Allow access to location services during this application
Property Description
Desiredaccuracy Positioning precision, enumeration type:

Kcllocationaccuracybest: The most accurate positioning
Cllocationaccuracy kcllocationaccuracynearesttenmeters: 10 meters Error Range
Kcllocationaccuracyhundredmeters: Hundred meters error Range
Kcllocationaccuracykilometer: Kilometer Error range
Kcllocationaccuracythreekilometers: 3-kilometer Error Range

Distancefilter Location information update minimum distance, only move greater than this distance to update location information, default is Kcldistancefilternone: No distance restrictions
Object methods Description
Startupdatinglocation Start positioning tracking, which will be performed according to the update frequency set by the user -(void) Locationmanager: (Cllocationmanager *) Manager didupdatelocations: (Nsarray *) locations; Method Feedback Positioning Information
Stopupdatinglocation STOP location Tracking
Startupdatingheading Start the navigation direction tracking
Stopupdatingheading Stop the navigation direction tracking
Startmonitoringforregion: Start locating a region and then start positioning the area. Call -(void) Locationmanager: (Cllocationmanager *) Manager if the user enters or walks out of a zone
Didenterregion: (clregion *) region
and -(void) Locationmanager: (Cllocationmanager *) Manager
Didexitregion: (clregion *) region
Proxy method feedback related information
Stopmonitoringforregion: Stop locating a region for tracking
Requestwheninuseauthorization Request to obtain the Location service authorization when the application is used, note that you want to configure the nslocationwheninuseusagedescription in Info.plist before using this method
Requestalwaysauthorization Request for application always use the Locator service authorization, note to configure nslocationalwaysusagedescription in Info.plist before using this method
Proxy method Description
-(void) Locationmanager: (Cllocationmanager *) Manager didupdatelocations: (Nsarray *) locations; Execution after a change in position (also performed after first positioning to a location)
-(void) Locationmanager: (Cllocationmanager *) Manager
Didupdateheading: (clheading *) newheading;
The navigation direction changes after the execution
-(void) Locationmanager: (Cllocationmanager *) Manager
Didenterregion: (Clregion *) region
Execute after entering a zone
-(void) Locationmanager: (Cllocationmanager *) Manager
Didexitregion: (Clregion *) region
Run out of a zone

IOS 8 also offers a more user-friendly positioning service option. App's location-based services are no longer just turned off or turned on, and now the location service is enabled with three options, "Never," and "Always." At the same time, considering the energy consumption problem, if an app requires always to open the location service in the background, IOS 8 will not only ask you when the app is first opened, but will also remind you in the daily use of the pop-up window that the app has been using location-based services in the background and asks if you want to continue In IOS7 and previous versions, if you use the location service in your application, you will be asked whether the user is allowed to use the positioning service if the Startupdatinglocation method application is invoked in the program. At the same time, you can configure Privacy-location Usage description to tell the user what to use in the Info.plist, and this configuration is optional.

However, configuration items have changed in IOS8 and can be configured nslocationalwaysusagedescription or nslocationwheninuseusagedescription to tell users the purpose of using the location service, And note that this configuration is required, if not configured by default, the application will not be able to use the positioning service, open the application does not give a prompt to open the positioning service, unless the installation of the application itself to set the positioning service. Also, in your application, you need to request a requestalwaysauthorization or Locationservicesenabled method based on configuration. Because my machine has been updated to the latest iOS8.1 the following content is mainly for iOS8, the use of iOS7 friends need to make a little adjustment.

KCMAINVIEWCONTROLLER.M//Corelocation////Created by Kenshin Cui on 14-03-27. Copyright (c) 2014 Kenshin Cui.
All rights reserved. #import "KCMainViewController.h" #import <CoreLocation/CoreLocation.h> @interface Kcmainviewcontroller ()

<cllocationmanagerdelegate>{Cllocationmanager *_locationmanager;}
  
  @end @implementation Kcmainviewcontroller-(void) viewdidload {[Super viewdidload];
  
  Locator manager _locationmanager=[[cllocationmanager Alloc]init]; if (![ Cllocationmanager locationservicesenabled]) {NSLog (@) location service may not be open at this moment, please set open!
    ");
  Return ///If authorization is not granted, request user authorization if ([Cllocationmanager authorizationstatus]==kclauthorizationstatusnotdetermined) {[_location
  Manager Requestwheninuseauthorization]; }else if ([Cllocationmanager authorizationstatus]==kclauthorizationstatusauthorizedwheninuse) {//Set proxy _locationMana
    ger.delegate=self;
    setting positioning accuracy _locationmanager.desiredaccuracy=kcllocationaccuracybest;
Positioning frequency, every number of meters to locate once    Cllocationdistance distance=10.0;//10 m positioning once _locationmanager.distancefilter=distance;
  Start tracking positioning [_locationmanager startupdatinglocation]; } #pragma mark-corelocation agent #pragma mark tracking Agent method, which executes whenever a change occurs (as long as the location is located)//can set a virtual location through the emulator, otherwise this method cannot be called in the Emulator-(void) Locationmanager: (Cllocationmanager *) Manager didupdatelocations: (Nsarray *) locations{cllocation Locations firstobject];//take out the first position cllocationcoordinate2d coordinate=location.coordinate;//position coordinates NSLog (@ Longitude:%f, Latitude:%f, Elevation:%f, heading:%f, walking speed:%f ", coordinate.longitude,coordinate.latitude,location.altitude,location.course,location.speed
  );
If you do not need real-time positioning, use the end even if the positioning service is closed [_locationmanager stopupdatinglocation];

 } @end

Attention:

1. Positioning frequency and positioning accuracy should not be the more accurate the better, depending on the actual situation, because the more accurate consumption of performance, the more the cost of electricity.

2. After the success of the positioning will be based on the settings frequently called-(void) Locationmanager: (Cllocationmanager *) Manager didupdatelocations: (Nsarray *) Locations method, This method returns an array of geographic objects, each with a cllocation representing geographic information (including longitude, latitude, posters, walking speed, and so on), and is returned because there are times when a location point may contain multiple locations.

3. After using the positioning service, if you do not need real-time monitoring should immediately turn off the positioning service to save resources.

4. In addition to providing a positioning function, Cllocationmanager can also invoke the Startmonitoringforregion: method to monitor the specified area.

Geo Code

In addition to providing location tracking, the location service includes the Clgeocoder class for handling geocoding and reverse geocoding (also called anti-geocoding) functionality.

Geocoding: Geographical coordinates (warp, latitude) are determined according to the given location (usually a place name).

Inverse geocoding: Location information (street, door number, etc.) can be determined according to geographical coordinates (warp, latitude).

The main two methods of Clgeocoder are-(void) geocodeaddressstring: (NSString *) addressstring Completionhandler: ( Clgeocodecompletionhandler) Completionhandler and-(void) Reversegeocodelocation: (cllocation *) location Completionhandler: (Clgeocodecompletionhandler) Completionhandler, respectively, for geo-coding and inverse geo-coding. Here's a quick demo:

KCMAINVIEWCONTROLLER.M//Corelocation////Created by Kenshin Cui on 14-03-27. Copyright (c) 2014 Kenshin Cui.
All rights reserved. #import "KCMainViewController.h" #import <CoreLocation/CoreLocation.h> @interface Kcmainviewcontroller ()

<cllocationmanagerdelegate>{Clgeocoder *_geocoder;}
  
  @end @implementation Kcmainviewcontroller-(void) viewdidload {[Super viewdidload];
  _geocoder=[[clgeocoder Alloc]init];
  [Self getcoordinatebyaddress:@ "Beijing"];
[Self getaddressbylatitude:39.54 longitude:116.28]; #pragma mark determines geographical coordinates based on geographical names-(void) Getcoordinatebyaddress: (NSString *) address{//geo-coding [_geocoder geocodeaddressstring:a Ddress completionhandler:^ (Nsarray *placemarks, Nserror *error) {//Get the first landmark, the landmark stores detailed address information, note: A place name may search for multiple addresses Clplace
    
    Mark *placemark=[placemarks Firstobject]; Cllocation *location=placemark.location;//Location clregion *region=placemark.region;//region NSDictionary *addressDic= emark.addressdictionary;//Detailed address information dictionary,Contains some information//nsstring *name=placemark.name;//place name//NSString *thoroughfare=placemark.thoroughfare;//Street//NSString *subthoroughfare=placemark.subthoroughfare; Street related information, such as house numbers//NSString *locality=placemark.locality; City//NSString *sublocality=placemark.sublocality; City-related information, such as landmark buildings//NSString *administrativearea=placemark.administrativearea; State//NSString *subadministrativearea=placemark.subadministrativearea; Other administrative area information//NSString *postalcode=placemark.postalcode; Zip//NSString *isocountrycode=placemark. Isocountrycode; National code//NSString *country=placemark.country; State//NSString *inlandwater=placemark.inlandwater; Water source, lake//NSString *ocean=placemark.ocean; Ocean//Nsarray *areasofinterest=placemark.areasofinterest;
  Associated or interest-related landmarks NSLog (@ "Location:%@, Area:%@, Details:%@", location,region,addressdic);
}]; #pragma mark obtains a place name based on coordinates (void) Getaddressbylatitude: (cllocationdegrees) Latitude Longitude: (cllocationdegrees) longitude{//Anti-geo coding Cllocation *location=[[cllocation Alloc]initwithlatitude:latitude Longitude:longitude]; [_geocoder reversegeocodelocation:location completionhandler:^ (Nsarray *placemarks, NSError *error)
    {Clplacemark *placemark=[placemarks firstobject];
  NSLog (@ "Detailed information:%@", placemark.addressdictionary);
}];

 } @end

Map

iOS from 6.0 start map data is no longer driven by Google, but instead use their own maps, of course, in the country its data is provided by the gold map. As a result, the use of the method would be different if the map was developed before the iOS6.0, and based on the current situation, the iOS6.0 version of the system was rarely used, and all the following content would not be introduced for IOS5 and previous versions of the map development.

There are two main ways to develop a map in iOS, one is the direct use of the MAPKIT framework for map development, the use of this method can be accurate control of the map; another way is to directly call Apple's official map application, mainly for some simple map applications (e.g., navigation cover padding, etc.) and cannot be controlled accurately. Of course, the main content of this section is the former, the following content will be slightly prompted.

Before using Mapkit, you need to get a brief look at some common properties and methods of Mapkit map display control Mkmapview, as shown in the following table:

Property Description
Usertrackingmode Trace type, is an enumeration:
Mkusertrackingmodenone: no user location tracking;
MKUSERTRACKINGMODEFOLLOW: Tracking user location;
Mkusertrackingmodefollowwithheading: Track user location and track user direction;
Maptype Map type, is an enumeration:
Mkmaptypestandard: Standard map, generally use this map can be satisfied;
Mkmaptypesatellite: satellite map;
Mkmaptypehybrid: Mixed maps, loading the slowest compared to consuming resources;
Userlocation User location, read-only property
Annotations All pins in the current map, read-only properties
Object methods Description
-(void) Addannotation: (id <MKAnnotation>) annotation; Add pin, corresponding to add pin array
-(void) Removeannotation: (id <MKAnnotation>) annotation; Remove Pins, corresponding to a delete pin array

-(void) Setregion: (mkcoordinateregion) region animated: (BOOL) animated;

Sets the map display area to control the current screen display map range
-(void) Setcentercoordinate: (cllocationcoordinate2d) Coordinate animated: (BOOL) animated; Set Map Center Point location
-(Cgpoint) Convertcoordinate: (cllocationcoordinate2d) Coordinate Topointtoview: (UIView *) view; Converts geographical coordinates (latitude and longitude) into mathematical coordinates (uikit coordinates)
-(Cllocationcoordinate2d) Convertpoint: (cgpoint) point tocoordinatefromview: (UIView *) view; Converts mathematical coordinates to geographical coordinates
-(Mkannotationview *) Dequeuereusableannotationviewwithidentifier: (NSString *) identifier; Remove pins from cache pool, similar to UITableViewCell in UITableView, designed for performance optimization
-(void) Selectannotation: (id <MKAnnotation>) annotation animated: (BOOL) animated; Select the specified pin
-(void) Deselectannotation: (id <MKAnnotation>) annotation animated: (BOOL) animated; Uncheck the specified pins
Proxy method Description
-(void) Mapview: (Mkmapview *) Mapview didupdateuserlocation: (mkuserlocation *) userlocation; Triggered when a user's location changes (the method is also triggered the first time you navigate to a user's location)
-(void) Mapview: (Mkmapview *) Mapview didupdateuserlocation: (mkuserlocation *) userlocation; Triggers when the display area has changed
-(void) Mapviewdidfinishloadingmap: (Mkmapview *) Mapview; triggered when map load is complete
-(Mkannotationview *) Mapview: (Mkmapview *) Mapview viewforannotation: (id <MKAnnotation>) annotation; When a pin is displayed, it returns a PIN view, which is usually done by a custom pin.
-(void) Mapview: (Mkmapview *) Mapview Didselectannotationview: (Mkannotationview *) view Click to select a PIN when triggered
-(void) Mapview: (Mkmapview *) Mapview Diddeselectannotationview: (Mkannotationview *) view Trigger when a pin is unchecked
-(Mkoverlayrenderer *) Mapview: (Mkmapview *) Mapview Rendererforoverlay: (ID <MKOverlay>) Overlay Trigger when rendering a map overlay

User Location Tracking

In many applications with maps, the default open map shows the user's current position, while the current position is marked out and placed on the screen to make it easier for users to view the surroundings. If you implement this functionality in IOS6 or IOS7, you only need to add map controls, set user tracking mode, and in-(void) Mapview: (Mkmapview *) Mapview didupdateuserlocation: ( Mkuserlocation *) Userlocation proxy method to set the Map center area and display range. But the usage is slightly different in iOS8:

1. Since the positioning function is required for user location tracking in the map, and the positioning function has changed in the iOS8 design, it must be configured and requested as described in the previous Location section.

2.ios8 does not require a central point designation, by default the current position is set to the center point and the display area range is automatically set.

To understand the above two points, the user location tracking is actually quite simple, worth mentioning is-(void) Mapview: (Mkmapview *) Mapview didupdateuserlocation: (mkuserlocation *) Userlocation this proxy method. This method is invoked only after positioning (using the positioning in the previous chapter) to the current position, which is triggered whenever the user's location changes, and the frequency of calls is quite frequent.

Pin

In the development of iOS will often mark a location, need to use map annotation, which is commonly known as the "pin." As long as a NSObject class implements the Mkannotation protocol as a pin, it usually overrides the coordinate (tag position), title (title), subtitle (subheadings) three attributes in the protocol. Then create a Pin object in the program and invoke Addannotation: method to add a pin (the reason why iOS does not define a base class to implement this protocol for developers to use, most of which should be Mkannotation is a model object, for most application models will be slightly different, For example, additional attributes are added to the Pin model object later in this section.

KCAnnotation.h


//KCAnnotation.h
//Mapkit////
Created by Kenshin Cui on 14/3/27.
Copyright (c) 2014 Kenshin Cui. All rights reserved.

#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>

@interface kcannotation: Nsobject<mkannotation>

@property (nonatomic) cllocationcoordinate2d coordinate;
@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *subtitle;

@end

Kcmainviewcontroller.m

KCMAINVIEWCONTROLLER.M//Mapkit Annotation////Created by Kenshin Cui on 14/3/27. Copyright (c) 2014 Kenshin Cui.
All rights reserved. 37.785834-122.406417//39.92 116.39 #import "KCMainViewController.h" #import &lt;CoreLocation/CoreLocation.h&gt; #i
  Mport &lt;MapKit/MapKit.h&gt; #import "KCAnnotation.h" @interface Kcmainviewcontroller () &lt;mkmapviewdelegate&gt;{
  Cllocationmanager *_locationmanager;
Mkmapview *_mapview;
  
  @end @implementation Kcmainviewcontroller-(void) viewdidload {[Super viewdidload];
[Self Initgui];
  #pragma mark adds a map control-(void) initgui{cgrect rect=[uiscreen mainscreen].bounds;
  _mapview=[[mkmapview Alloc]initwithframe:rect];
  [Self.view Addsubview:_mapview];
  
  Set up Agent _mapview.delegate=self;
  Request Location Service _locationmanager=[[cllocationmanager Alloc]init]; if (![ Cllocationmanager locationservicesenabled]| | [Cllocationmanager authorizationstatus]!=kclauthorizationstatusauthorizedwheninuse) {[_locationManager requestWheNinuseauthorization];
  
  }//User location Tracking (user location tracking is used to mark the current location of the user, the location service will be invoked) _mapview.usertrackingmode=mkusertrackingmodefollow;
  
  Set the map type _mapview.maptype=mkmaptypestandard;
Add pin [self addannotation]; #pragma mark add pin-(void) addannotation{cllocationcoordinate2d location1=cllocationcoordinate2dmake (39.95, 116.35)
  ;
  Kcannotation *annotation1=[[kcannotation Alloc]init];
  annotation1.title=@ "CMJ Studio";
  annotation1.subtitle=@ "Kenshin Cui ' s Studios";
  Annotation1.coordinate=location1;
  
  [_mapview Addannotation:annotation1];
  Cllocationcoordinate2d Location2=cllocationcoordinate2dmake (39.87, 116.35);
  Kcannotation *annotation2=[[kcannotation Alloc]init];
  annotation2.title=@ "Kenshin&amp;kaoru";
  annotation2.subtitle=@ "Kenshin Cui ' s Home";
  Annotation2.coordinate=location2;
[_mapview Addannotation:annotation2]; #pragma mark-Map control proxy method #pragma mark updates the user's location and calls this method (including the first time to the user's location) when the user changes-(void) Mapview: (Mkmapview *) Mapview Didupdateus Erlocation: (Mkuserlocation *) userlocation{NSLog (@ "%@", userlocation);
  Sets the map display range (automatically displays the area range if no locale is set and specifies the current user location as the Map center point)//Mkcoordinatespan Span=mkcoordinatespanmake (0.01, 0.01);
  Mkcoordinateregion Region=mkcoordinateregionmake (userLocation.location.coordinate, span);
[_mapview setregion:region animated:true];

 } @end

Operation Effect:

Set PIN view

In some applications the system default PIN style may not meet the actual requirements, at this point you need to modify the PIN view default style. Based on the previous Mapkit proxy method is not difficult to find-(Mkannotationview *) Mapview: (Mkmapview *) Mapview viewforannotation: (ID <MKAnnotation>) Annotation method can return a pin view, as long as you implement this method and define a PIN view Mkannotationview object in this method and set the related properties to change the default PIN style. Mkannotationview Common Properties:

Property Description
Annotation Pin model information, including title, subheadings, geographic location.
Image Pin picture
Canshowcallout Click whether the pin displays title, subheadings, etc., note if in -(Mkannotationview *) Mapview: (Mkmapview *) Mapview viewforannotation: (ID < mkannotation>) annotation; method to redefine the pins by default, the need to set to true cannot be interacted.
Calloutoffset Click the pin when the pop-up details view offset
Selected Whether the state is selected
Leftcalloutaccessoryview Popup Details Left View
Rightcalloutaccessoryview Popup Details Right View

Need to note:

A. Timing of this proxy method: This method is called whenever a pin is displayed in the system's visual interface, and a PIN view is returned to the interface, and the current system position callout (that is, the blue position in the map) is also a pin, and this method is called, so the pin view needs to be treated differently.

B. Similar to the UITableView proxy method, this method calls frequently, the development process needs to reuse the Mapkit cache pool to cache the pin view to reuse.

C. Custom Pins the interaction is not allowed by default, if the interaction needs to be set Canshowcallout=true

D. If the Proxy method returns nil, the default PIN view is used, which is set according to the situation.

The following is a sample pin view setting, where you set the picture of the pin, the pop-up view, the offset, and so on.

KCAnnotation.h


//KCAnnotation.h
//Mapkit////
Created by Kenshin Cui on 14/3/27.
Copyright (c) 2014 Kenshin Cui. All rights reserved.

#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>

@interface kcannotation: Nsobject<mkannotation>

@property (nonatomic) cllocationcoordinate2d coordinate;
@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *subtitle;

#pragma mark customizes a picture property to use
@property (nonatomic,strong) UIImage *image When creating a pin view;

@end

Kcmainviewcontroller.m

KCMAINVIEWCONTROLLER.M//Mapkit Annotation////Created by Kenshin Cui on 14/3/27. Copyright (c) 2014 Kenshin Cui.
All rights reserved. 37.785834-122.406417//39.92 116.39 #import "KCMainViewController.h" #import &lt;CoreLocation/CoreLocation.h&gt; #i
  Mport &lt;MapKit/MapKit.h&gt; #import "KCAnnotation.h" @interface Kcmainviewcontroller () &lt;mkmapviewdelegate&gt;{
  Cllocationmanager *_locationmanager;
Mkmapview *_mapview;
  
  @end @implementation Kcmainviewcontroller-(void) viewdidload {[Super viewdidload];
[Self Initgui];
  #pragma mark adds a map control-(void) initgui{cgrect rect=[uiscreen mainscreen].bounds;
  _mapview=[[mkmapview Alloc]initwithframe:rect];
  [Self.view Addsubview:_mapview];
  
  Set up Agent _mapview.delegate=self;
  Request Location Service _locationmanager=[[cllocationmanager Alloc]init]; if (![ Cllocationmanager locationservicesenabled]| | [Cllocationmanager authorizationstatus]!=kclauthorizationstatusauthorizedwheninuse) {[_locationManager requestWheNinuseauthorization];
  
  }//User location Tracking (user location tracking is used to mark the current location of the user, the location service will be invoked) _mapview.usertrackingmode=mkusertrackingmodefollow;
  
  Set the map type _mapview.maptype=mkmaptypestandard;
Add pin [self addannotation]; #pragma mark add pin-(void) addannotation{cllocationcoordinate2d location1=cllocationcoordinate2dmake (39.95, 116.35)
  ;
  Kcannotation *annotation1=[[kcannotation Alloc]init];
  annotation1.title=@ "CMJ Studio";
  annotation1.subtitle=@ "Kenshin Cui ' s Studios";
  Annotation1.coordinate=location1;
  Annotation1.image=[uiimage imagenamed:@ "Icon_pin_floating.png"];
  
  [_mapview Addannotation:annotation1];
  Cllocationcoordinate2d Location2=cllocationcoordinate2dmake (39.87, 116.35);
  Kcannotation *annotation2=[[kcannotation Alloc]init];
  annotation2.title=@ "Kenshin&amp;kaoru";
  annotation2.subtitle=@ "Kenshin Cui ' s Home";
  Annotation2.coordinate=location2;
  Annotation2.image=[uiimage imagenamed:@ "Icon_paopao_waterdrop_streetscape.png"]; [_mapview Addannotation:annotation2];
#pragma mark-Map control proxy method #pragma mark displays pins, note that the annotation parameter in the method is the Pin object that is about to be displayed-(Mkannotationview *) Mapview: (Mkmapview *) Mapview viewforannotation: (id&lt;mkannotation&gt;) annotation{//Because the callout at the current position is also a pin, it is time to judge that this proxy method returns nil using the default PIN view if ( [Annotation iskindofclass:[kcannotation class]]
    {static NSString *key1=@ "AnnotationKey1";
    Mkannotationview *annotationview=[_mapview Dequeuereusableannotationviewwithidentifier:key1]; If the cache pool does not exist, the new if (!annotationview) {Annotationview=[[mkannotationview alloc]initwithannotation:annotation reus
      Eidentifier:key1]; annotationview.canshowcallout=true;//Allow interactive Click Annotationview.calloutoffset=cgpointmake (0, 1);//Define Detail View offset Annotat Ionview.leftcalloutaccessoryview=[[uiimageview alloc]initwithimage:[uiimage imagenamed:@ "Icon_classify_cafe.png" ]];//definition details Left view}//Modify PIN View/PIN model to reset this type of pin view (because it is possible to be taken out of the cache pool, where it is placed in the cache pool) Annotationview.annotation=ann
    Otation; Annotationview.image= ((kcannotation *) AnnotatiON). image;//set the picture of the pin view return annotationview;
  }else {return nil;

 }} @end

Operation Effect:

Attention:

In the Mapkit framework there is a mkpinannotationview in addition to Mkannotationview, which is a subclass of Mkannotationview, Compared to mkannotationview two attributes Pincolor and Animationdrop are used to set the PIN view color and add a pin animation, respectively.

Extension-Custom pin bullet Details view

It's not hard to see through the example above that Mkannotationview is strong enough (not to mention Mkpinannotationview), and that a lot of information can be set up, but you can't change the pin description Details view (only supports the left and right view content in details). In order to achieve this demand the current development of the common idea is:

A. When clicking a pin a, re-add another pin b at the coordinates of a (note that at this point the pin view canshowcallout of A is set to false) as the pin detail model and then in-(Mkannotationview *) Mapview: ( Mkmapview *) Mapview viewforannotation: (id <MKAnnotation>) annotation, proxy method to determine the type of pin, If b, rewrite Mkannotationview (you can customize a class C to inherit from Mkannotationview), and return to the custom pin view C.

B. Define PIN view C inherits from Mkannotationview (or Mkpinannotationview), adds its own controls to the custom Pin view, and completes the custom layout.

In the use of Baidu Map client when you click a search location can see this position evaluation and other information, the view effect is probably as follows:

Let's try to achieve this effect:

Pin Model: KCAnnotation.h


//KCAnnotation.h
//Mapkit////
Created by Kenshin Cui on 14/3/27.
Copyright (c) 2014 Kenshin Cui. All rights reserved.

#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>

@interface kcannotation: Nsobject<mkannotation>

@property (nonatomic) cllocationcoordinate2d coordinate;
@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *subtitle;

#pragma mark customizes a picture property to use
@property (nonatomic,strong) UIImage *image When creating a pin view;

#pragma mark pin details left icon
@property (nonatomic,strong) uiimage *icon;
#pragma mark Pin details description 
@property (nonatomic,copy) nsstring *detail;
#pragma mark pin right lower star rating
@property (nonatomic,strong) uiimage *rate;

@end

Pop-up details pin model: KCCalloutAnnotation.h

KCCalloutAnnotation.h//Mapkit////Created by Kenshin Cui on 14/3/27. Copyright (c) 2014 Kenshin Cui.
All rights reserved. #import &lt;UIKit/UIKit.h&gt; #import &lt;CoreLocation/CoreLocation.h&gt; #import &lt;MapKit/MapKit.h&gt; @
Interface kccalloutannotation:nsobject&lt;mkannotation&gt; @property (nonatomic) cllocationcoordinate2d coordinate;
@property (nonatomic, copy,readonly) NSString *title;

@property (nonatomic, copy,readonly) NSString *subtitle;
#pragma Mark's left icon @property (nonatomic,strong) uiimage *icon;
#pragma mark details describe @property (nonatomic,copy) NSString *detail;

#pragma mark star rating @property (Nonatomic,strong) uiimage *rate;
@end Pop-up details pin view: KCCalloutAnnotatonView.h////KCCALLOUTVIEW.H//Mapkit///Created by Kenshin Cui on 14/3/27. Copyright (c) 2014 Kenshin Cui.
All rights reserved. Custom pop-up label gaze #import &lt;UIKit/UIKit.h&gt; #import &lt;CoreLocation/CoreLocation.h&gt; #import &lt;mapkit/mapkit.h &gt; #import "KCCalloutAnnotation.h" @interfaCe Kccalloutannotationview:mkannotationview @property (nonatomic, strong) kccalloutannotation *annotation;

#pragma mark Calloutviewwithmapview from cache (instancetype): (Mkmapview *) Mapview;
@end KCCALLOUTANNOTATIONVIEW.M////KCCALLOUTVIEW.M//Mapkit///Created by Kenshin Cui on 14/3/27. Copyright (c) 2014 Kenshin Cui.
All rights reserved. #import "KCCalloutAnnotationView.h" #define kspacing 5 #define KDETAILFONTSIZE #define KVIEWOFFSET @interface K
  Ccalloutannotationview () {UIView *_backgroundview;
  Uiimageview *_iconview;
  Uilabel *_detaillabel;
Uiimageview *_rateview;
  @end @implementation Kccalloutannotationview-(instancetype) init{if (self=[super init)) {[Self layoutui];
return self;
  }-(Instancetype) initWithFrame: (CGRect) frame{if (Self=[super Initwithframe:frame]) {[Self layoutui];
return self;
  }-(void) layoutui{//Background _backgroundview=[[uiview alloc]init];
  _backgroundview.backgroundcolor=[uicolor Whitecolor]; //Add icon to the left _iconview=[[uiimageview Alloc]init];
  Above details _detaillabel=[[uilabel Alloc]init];
  _detaillabel.linebreakmode=nslinebreakbywordwrapping;
  [_text SizeToFit];
  
  _detaillabel.font=[uifont Systemfontofsize:kdetailfontsize];
  
  Lower star _rateview=[[uiimageview Alloc]init];
  [Self addsubview:_backgroundview];
  [Self addsubview:_iconview];
  [Self Addsubview:_detaillabel];
[Self addsubview:_rateview];
  } + (Instancetype) Calloutviewwithmapview: (Mkmapview *) mapview{static nsstring *calloutkey=@ "CalloutKey1"; Kccalloutannotationview *calloutview= (Kccalloutannotationview *) [Mapview
  Dequeuereusableannotationviewwithidentifier:calloutkey];
  if (!calloutview) {Calloutview=[[kccalloutannotationview alloc]init];
return calloutview; #pragma mark when you set the PIN model for the PIN view, you can set the view content based on the model at this point-(void) Setannotation: (kccalloutannotation *) annotation{[super
  Setannotation:annotation];
  Adjust layout _iconview.image=annotation.icon according to the model; _iconview.frame=cgrectmake (kspacing, KspacING, annotation.icon.size.width, annotation.icon.size.height);
  _detaillabel.text=annotation.detail;
  float detailwidth=150.0; Cgsize detailsize= [Annotation.detail boundingrectwithsize:cgsizemake (DetailWidth, MAXFLOAT) options: Nsstringdrawinguseslinefragmentorigin attributes:@{nsfontattributename: [Uifont systemFontOfSize:kDetailFontSize]
  } context:nil].size;
  Float Detailx=cgrectgetmaxx (_iconview.frame) +kspacing;
  _detaillabel.frame=cgrectmake (DETAILX, kspacing, Detailsize.width, detailsize.height);
  _rateview.image=annotation.rate; _rateview.frame=cgrectmake (DETAILX, Cgrectgetmaxy (_detaillabel.frame) +kspacing, Annotation.rate.size.width,
  
  Annotation.rate.size.height);
  Float Backgroundwidth=cgrectgetmaxx (_detaillabel.frame) +kspacing;
  float backgroundheight=_iconview.frame.size.height+2*kspacing;
  _backgroundview.frame=cgrectmake (0, 0, backgroundwidth, backgroundheight);
  
Self.bounds=cgrectmake (0, 0, backgroundwidth, backgroundheight+kviewoffset);

 } @end

Main View controller: KCMAINVIEWCONTROLLER.M

KCMAINVIEWCONTROLLER.M//Mapkit Annotation////Created by Kenshin Cui on 14/3/27. Copyright (c) 2014 Kenshin Cui.
All rights reserved. 37.785834-122.406417//39.92 116.39 #import "KCMainViewController.h" #import &lt;CoreLocation/CoreLocation.h&gt; #i Mport &lt;MapKit/MapKit.h&gt; #import "KCAnnotation.h" #import "KCCalloutAnnotationView.h" #import " KCCalloutAnnotationView.h "@interface Kcmainviewcontroller () &lt;mkmapviewdelegate&gt;{Cllocationmanager *_
  Locationmanager;
Mkmapview *_mapview;
  
  @end @implementation Kcmainviewcontroller-(void) viewdidload {[Super viewdidload];
[Self Initgui];
  #pragma mark adds a map control-(void) initgui{cgrect rect=[uiscreen mainscreen].bounds;
  _mapview=[[mkmapview Alloc]initwithframe:rect];
  [Self.view Addsubview:_mapview];
  
  Set up Agent _mapview.delegate=self;
  Request Location Service _locationmanager=[[cllocationmanager Alloc]init]; if (![ Cllocationmanager locationservicesenabled]| | [Cllocationmanager Authorizationstatus]!=kclaUthorizationstatusauthorizedwheninuse) {[_locationmanager requestwheninuseauthorization];
  
  }//User location Tracking (user location tracking is used to mark the current location of the user, the location service will be invoked) _mapview.usertrackingmode=mkusertrackingmodefollow;
  
  Set the map type _mapview.maptype=mkmaptypestandard;
Add pin [self addannotation]; #pragma mark add pin-(void) addannotation{cllocationcoordinate2d location1=cllocationcoordinate2dmake (39.95, 116.35)
  ;
  Kcannotation *annotation1=[[kcannotation Alloc]init];
  annotation1.title=@ "CMJ Studio";
  annotation1.subtitle=@ "Kenshin Cui ' s Studios";
  Annotation1.coordinate=location1;
  Annotation1.image=[uiimage imagenamed:@ "Icon_pin_floating.png"];
  Annotation1.icon=[uiimage imagenamed:@ "Icon_mark1.png"];
  annotation1.detail=@ "CMJ Studio ...";
  Annotation1.rate=[uiimage imagenamed:@ "Icon_movie_star_rating.png"];
  
  [_mapview Addannotation:annotation1];
  Cllocationcoordinate2d Location2=cllocationcoordinate2dmake (39.87, 116.35);
  Kcannotation *annotation2=[[kcannotation Alloc]init]; Annotation2.title=@ "Kenshin&amp;kaoru";
  annotation2.subtitle=@ "Kenshin Cui ' s Home";
  Annotation2.coordinate=location2;
  Annotation2.image=[uiimage imagenamed:@ "Icon_paopao_waterdrop_streetscape.png"];
  Annotation2.icon=[uiimage imagenamed:@ "Icon_mark2.png"];
  annotation2.detail=@ "Kenshin Cui ...";
  Annotation2.rate=[uiimage imagenamed:@ "Icon_movie_star_rating.png"];
[_mapview Addannotation:annotation2]; #pragma mark-Map control proxy method #pragma mark displays pins, note that the annotation parameter in the method is the Pin object that is about to be displayed-(Mkannotationview *) Mapview: (Mkmapview *) Mapview viewforannotation: (id&lt;mkannotation&gt;) annotation{//Because the callout at the current position is also a pin, it is time to judge that this proxy method returns nil using the default PIN view if ( [Annotation iskindofclass:[kcannotation class]]
    {static NSString *key1=@ "AnnotationKey1";
    Mkannotationview *annotationview=[_mapview Dequeuereusableannotationviewwithidentifier:key1]; If the cache pool does not exist, the new if (!annotationview) {Annotationview=[[mkannotationview alloc]initwithannotation:annotation reus
Eidentifier:key1]; Annotationview.canshowcallout=true;//Allow interactive Click Annotationview.calloutoffset=cgpointmake (0, 1);//Define Detail View offset Annotatio Nview.leftcalloutaccessoryview=[[uiimageview alloc]initwithimage:[uiimage imagenamed:@ "Icon_classify_cafe.png"] //define details Left view}//Modify PIN View/PIN model to reset this type of pin view (since it may be taken out of the cache pool, where it is placed in the cache pool) Annotationview.annotation=annot
    ation
  Annotationview.image= ((kcannotation *) annotation). image;//Set the pin view picture return annotationview; }else if ([Annotation iskindofclass:[kccalloutannotation class]]) {//No pop-up interactivity for a custom pin view as a pop-up detail view (canshowcallout= False, which is the default value, in which other views can be added freely (because it inherits from UIView) Kccalloutannotationview *calloutview=[kccalloutannotationview
    Calloutviewwithmapview:mapview];
    Calloutview.annotation=annotation;
  return calloutview;
  else {return nil; } #pragma mark when a PIN is selected triggers//clicks the general pin kcannotation to add a pin to the pop-up details view of the point pin-(void) Mapview: (Mkmapview *) Mapview Didselectannotationview: (Mkannotationview *) view{kcannotation *annotatiOn=view.annotation;
    if ([View.annotation Iskindofclass:[kcannotation class]]) {//Click a pin to remove other pop-up details view//[self removecustomannotation];
    Add details PIN, render this pin view to the custom pin view to complete the automatic layout kccalloutannotation *annotation1=[[kccalloutannotation Alloc]init];
    Annotation1.icon=annotation.icon;
    Annotation1.detail=annotation.detail;
    Annotation1.rate=annotation.rate;
    Annotation1.coordinate=view.annotation.coordinate;
  [Mapview Addannotation:annotation1]; #pragma mark was unchecked when he was unchecked-(void) Mapview: (Mkmapview *) Mapview Diddeselectannotationview: (Mkannotationview *) view{[self
Removecustomannotation]; #pragma mark removes the custom pin-(void) removecustomannotation{[_mapview.annotations enumerateobjectsusingblock:^ (id obj, NS UInteger idx, BOOL *stop) {if ([obj Iskindofclass:[kccalloutannotation class]]) {[_mapview Removeannotation:ob
    J];
}
  }]; 

 } @end

There are a few things to note in this process:

1. Pin A as a common pin, it is best to save the custom PIN view C required model to initialize the view according to different models.

2. Custom PIN view C PIN Model B does not require the title, subtitle property, preferably set to read-only; the layout model data that you need to last save custom pin view C in the model.

3. Only click on a non-B pin only to add a custom pin, and the increase should first remove other B-type pins to avoid overlap (generally recommended to remove the PIN selected Agent method).

4. Usually in the custom PIN view C Set PIN model layout interface, at this point need to pay attention to the position of the new PIN, usually need to offset a certain distance to achieve the desired effect.

Operation Effect:

Using a self-band map application

In addition to the use of the Mapkit framework for map development, accurate control and customization of the map, if there is no special requirements for the application of the use of Apple's own map application is also a good choice. Using an Apple-band application requires the Mkmapitem class in Mapkit, which has a openinmapswithlaunchoptions: Dynamic method and a openmapswithitems:launchoptions: The static method is used to open the Apple map application. The first method is used to mark a location on the map, and the second method can be used to navigate between multiple locations in addition to being able to mark multiple locations, which is also quite handy to use. Before you are familiar with the two methods, it is necessary to make a brief description of the options parameters in the two methods:

Keys (constants) Description Value
Mklaunchoptionsdirectionsmodekey Route mode, constant Mklaunchoptionsdirectionsmodedriving driving mode
Mklaunchoptionsdirectionsmodewalking Walking mode
Mklaunchoptionsmaptypekey Map types, enumerating Mkmaptypestandard: Standard mode
Mkmaptypesatellite: Satellite mode
Mkmaptypehybrid: Blending mode
Mklaunchoptionsmapcenterkey Center point coordinates, CLLOCATIONCOORDINATE2D type
Mklaunchoptionsmapspankey Map display span, Mkcoordinatespan type
Mklaunchoptionsshowstraffickey Whether to show traffic conditions, Boolean
Mklaunchoptionscamerakey 3D map effect, Mkmapcamera type
Note: This property is available from IOS7 and later, and the previous properties are available from iOS6

Annotations in a single position

The following code shows how to mark a position on an Apple map application, first obtain a Clplacemark position object based on the reverse geocoding, and then convert it to a Mkplacemark object for Mkmapitem initialization. Finally call its openinmapswithlaunchoptions: Open the Map application and mark:

KCMAINVIEWCONTROLLER.M//APPLEMAP////Created by Kenshin Cui on 14/3/27. Copyright (c) 2014 Kenshin Cui.
All rights reserved. #import "KCMainViewController.h" #import &lt;CoreLocation/CoreLocation.h&gt; #import &lt;MapKit/MapKit.h&gt; @
Interface Kcmainviewcontroller () @property (Nonatomic,strong) Clgeocoder *geocoder;
  
  @end @implementation Kcmainviewcontroller-(void) viewdidload {[Super viewdidload];
  
  _geocoder=[[clgeocoder Alloc]init];
[Self location]; #pragma mark locates on the map-(void) location{///In accordance with the "Beijing" Geographic Code [_geocoder geocodeaddressstring:@ "Beijing" completionhandler:^ (NSA Rray *placemarks, Nserror *error) {Clplacemark *clplacemark=[placemarks firstobject];//get first landmark MKPlacemark Cemark=[[mkplacemark alloc]initwithplacemark:clplacemark];//positioning landmark into a map of landmarks Nsdictionary *options=@{
    mklaunchoptionsmaptypekey:@ (Mkmaptypestandard)};
    Mkmapitem *mapitem=[[mkmapitem Alloc]initwithplacemark:mkplacemark]; [Mapitem openinmapswithlaunchoptions:Options];
}];

 } @end

Operation Effect:

Mark Multiple Locations

If you want to mark multiple locations to invoke a static method of Mkmapitem, the following code demonstrates that you can only navigate to one location at a time using Clgeocoder, so the second position is positioned after the first position has been successfully obtained.

KCMAINVIEWCONTROLLER.M//APPLEMAP////Created by Kenshin Cui on 14/3/27. Copyright (c) 2014 Kenshin Cui.
All rights reserved. #import "KCMainViewController.h" #import &lt;CoreLocation/CoreLocation.h&gt; #import &lt;MapKit/MapKit.h&gt; @
Interface Kcmainviewcontroller () @property (Nonatomic,strong) Clgeocoder *geocoder;
  
  @end @implementation Kcmainviewcontroller-(void) viewdidload {[Super viewdidload];
  
  _geocoder=[[clgeocoder Alloc]init];
[Self listplacemark]; }-(void) listplacemark{//In accordance with "Beijing" geographical Coding [_geocoder geocodeaddressstring:@ "Beijing" completionhandler:^ (Nsarray *placemar KS, Nserror *error) {Clplacemark *clplacemark1=[placemarks firstobject];//get the first landmark Mkplacemark *mkPlacemark1=[[MKP
    Lacemark ALLOC]INITWITHPLACEMARK:CLPLACEMARK1]; Note that geocoding can only be positioned to one location at a time, not positioned at the same time, placed in the first position in the complete callback function to locate again [_geocoder geocodeaddressstring:@ "Zhengzhou" completionhandler:^ ( Nsarray *placemarks, Nserror *error) {Clplacemark *clplacemark2=[placemarks firstobject];//Get the first landmark Mkplacemark *mkplacemark2=[[mkplacemark ALLOC]INITWITHPLACEMARK:CLPLACEMARK2];
      Nsdictionary *options=@{mklaunchoptionsmaptypekey:@ (Mkmaptypestandard)}; Mkmapitem *mapitem1=[mkmapitem mapitemforcurrentlocation];//Current position Mkmapitem *mapitem1=[[mkmapitem alloc]initWithPl
      ACEMARK:MKPLACEMARK1];
      Mkmapitem *mapitem2=[[mkmapitem ALLOC]INITWITHPLACEMARK:MKPLACEMARK2];
      
    [Mkmapitem openmapswithitems:@[mapitem1,mapitem2] launchoptions:options];
    
  }];
}];

 } @end

Operation Effect:

Map navigation

To use the map navigation function is quite simple in your own map application, as long as you set the parameters to configure the navigation mode, such as setting the driving mode on the basis of the above code, the map application will start the driving mode to calculate the distance between two points and plan the route.

KCMAINVIEWCONTROLLER.M//APPLEMAP////Created by Kenshin Cui on 14/3/27. Copyright (c) 2014 Kenshin Cui.
All rights reserved. #import "KCMainViewController.h" #import &lt;CoreLocation/CoreLocation.h&gt; #import &lt;MapKit/MapKit.h&gt; @
Interface Kcmainviewcontroller () @property (Nonatomic,strong) Clgeocoder *geocoder;
  
  @end @implementation Kcmainviewcontroller-(void) viewdidload {[Super viewdidload];
  
  _geocoder=[[clgeocoder Alloc]init];
[Self turnbyturn]; }-(void) turnbyturn{//According to "Beijing" geo-coding [_geocoder geocodeaddressstring:@ "Beijing" completionhandler:^ (Nsarray *placemarks, NS Error *error) {Clplacemark *clplacemark1=[placemarks firstobject];//get first landmark Mkplacemark *mkplacemark1=[[mkplacema
    RK ALLOC]INITWITHPLACEMARK:CLPLACEMARK1]; Note that geocoding can only be positioned to one location at a time, not positioned at the same time, placed in the first position in the complete callback function to locate again [_geocoder geocodeaddressstring:@ "Zhengzhou" completionhandler:^ ( Nsarray *placemarks, Nserror *error) {Clplacemark *clplacemark2=[placemarks firstobject];//get firstLandmark Mkplacemark *mkplacemark2=[[mkplacemark ALLOC]INITWITHPLACEMARK:CLPLACEMARK2]; Nsdictionary *options=@{mklaunchoptionsmaptypekey:@ (Mkmaptypestandard), Mklaunchoptionsdirectionsmodekey:
      Mklaunchoptionsdirectionsmodedriving}; Mkmapitem *mapitem1=[mkmapitem mapitemforcurrentlocation];//Current position Mkmapitem *mapitem1=[[mkmapitem alloc]initWithPl
      ACEMARK:MKPLACEMARK1];
      Mkmapitem *mapitem2=[[mkmapitem ALLOC]INITWITHPLACEMARK:MKPLACEMARK2];
      
    [Mkmapitem openmapswithitems:@[mapitem1,mapitem2] launchoptions:options];
    
  }];
}];

 } @end

Operation Effect:

Note: In fact, if you do not use the use of the map of the Apple Map Navigation, Mapkit provides a Mkdirectionrequest object for the calculation of the route, provided mkdirections for the calculation of the direction, Such a dozen need to call the Mkmapview Addoverlay and other methods to add a cover to achieve similar effects, interested friends can try.

Because of the positioning and map frame used in many classes, some beginners are easy to confuse, the following simple contrast.

Cllocation: Used to represent location information, including geographical coordinates, elevation and other information, included in the Coreloaction framework.

Mkuserlocation: A special pin that represents the user's current position.

Clplacemark: A landmark in the positioning framework that encapsulates detailed geographic information.

Mkplacemark: Similar to Clplacemark, it's just in the Mapkit frame, you can create mkplacemark based on Clplacemark.

Original link: http://www.cnblogs.com/kenshincui/p/4125570.html

The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.