Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 89 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
89
Dung lượng
2,17 MB
Nội dung
CHAPTER 6 Core Location and Maps 6.0 Introduction The Core Location and Map Kit frameworks can be used to create location-aware and map-based applications. The Core Location framework uses the internal device’s hard- ware to determine the current location of the device. The Map Kit framework enables your application to display maps to your users, put custom annotations on the maps, and so on. The availability of location services depends on the availability of hardware on the device; if the hardware is there, it must be enabled and switched on for the Map Kit framework to work. To use the Core Location and Map Kit frameworks, you need to first add them to your project and make sure appropriate header files are imported. Follow these steps to add these two frameworks to your project: 1. Click on your project icon in Xcode. 2. Select the target to which you want to add the frameworks to, as shown in Fig- ure 6-1. 3. Now select the Build Phases tab on the top (Figure 6-1). 4. Expand the Link Binary With Libraries box (Figure 6-1) and press the + button. 429 Figure 6-1. Selecting the target to which we want to add the frameworks 5. In the dialog, you will see the list of all available frameworks and static libraries. Find and select both the CoreLocation.framework and the MapKit.framework and then press Add, as shown in Figure 6-2. 430 | Chapter 6: Core Location and Maps Figure 6-2. Adding the CoreLocation and the MapKit frameworks to a project After adding these two frameworks, you will need to add two header files to your .m or .h file (in your .h file if you are referring to any entity that is included in either of the two aforementioned frameworks): #import <CoreLocation/CoreLocation.h> #import <MapKit/MapKit.h> 6.1 Creating a Map View Problem You want to instantiate and display a map on a view. Solution Create an instance of the MKMapView class and add it to a view or assign it as a subview of your view controller. Here is the sample .h file of a view controller that creates an instance of MKMapView and displays it full-screen on its view: #import <UIKit/UIKit.h> #import <MapKit/MapKit.h> 6.1 Creating a Map View | 431 @interface Creating_a_Map_ViewViewController : UIViewController @property (nonatomic, strong) MKMapView *myMapView; @end This is a simple root view controller with a variable of type MKMapView. Later in the implementation of this view controller (.m file), we will initialize the map and set its type to Satellite, like so: #import "Creating_a_Map_ViewViewController.h" @implementation Creating_a_Map_ViewViewController @synthesize myMapView; - (void)didReceiveMemoryWarning{ [super didReceiveMemoryWarning]; } - (void)viewDidLoad{ [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; self.myMapView = [[MKMapView alloc] initWithFrame:self.view.bounds]; /* Set the map type to Satellite */ self.myMapView.mapType = MKMapTypeSatellite; self.myMapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; /* Add it to our view */ [self.view addSubview:self.myMapView]; } - (void)viewDidUnload{ [super viewDidUnload]; self.myMapView = nil; } - (BOOL)shouldAutorotateToInterfaceOrientation :(UIInterfaceOrientation)interfaceOrientation{ return YES; } @end 432 | Chapter 6: Core Location and Maps Discussion Creating an instance of the MKMapView class is quite straightforward. We can simply assign a frame to it using its constructor, and after the map is created, we will add it as a subview of the view on the screen just so that we can see it. MKMapView is a subclass of UIView, so you can manipulate any map view the way you manipulate an instance of UIView. If you haven’t already noticed, the MKMapView class has a property called mapType that can be set to satellite, standard, or hybrid. In this example, we are using the satellite map type (see Figure 6-3). 6.1 Creating a Map View | 433 Figure 6-3. A satellite map view We can change the visual representation type of a map view using the mapType property of an instance of MKMapView. Here are the different values we can use for this property: MKMapTypeStandard Use this map type to display a standard map (this is the default). MKMapTypeSatellite Use this map type to display a satellite image map (as depicted in Figure 6-3). MKMapTypeHybrid Use this map type to display a standard map overlaid on a satellite image map. 434 | Chapter 6: Core Location and Maps See Also XXX 6.2 Handling the Events of a Map View Problem You want to handle various events that a map view can send to its delegate. Solution Assign a delegate object, which conforms to the MKMapViewDelegate protocol, to the delegate property of an instance of the MKMapView class: /* Create a map as big as our view */ self.myMapView = [[MKMapView alloc] initWithFrame:self.view.bounds]; /* Set the map type to Satellite */ self.myMapView.mapType = MKMapTypeSatellite; self.myMapView.delegate = self; self.myMapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; /* Add it to our view */ [self.view addSubview:self.myMapView]; This code can easily run in the viewDidLoad method of a view controller object that has a property named MapView of type MKMapView: #import <UIKit/UIKit.h> #import <MapKit/MapKit.h> @interface Handling_the_Events_of_a_Map_ViewViewController : UIViewController <MKMapViewDelegate> @property (nonatomic, strong) MKMapView *myMapView; @end Discussion The delegate object of an instance of the MKMapView class must implement the methods defined in the MKMapViewDelegate protocol in order to receive various messages from the map view and, as we will see later, to be able to provide information to the map view. Various methods are defined in the MKMapViewDelegate protocol, such as the mapViewWillStartLoadingMap: method that will get called in the delegate object when- 6.2 Handling the Events of a Map View | 435 ever the map loading process starts. Bear in mind that a delegate for a map view is not a required object, meaning that you can create map views without assigning delegates to them; these views simply won’t respond to user manipulation. Here is a list of some of the methods declared in the MKMapViewDelegate protocol and what they are meant to report to the delegate object of an instance of MKMapView: mapViewWillStartLoadingMap: This method is called on the delegate object whenever the map view starts to load the data that visually represents the map to the user. mapView:viewForAnnotation: This method is called on the delegate object whenever the map view is asking for an instance of MKAnnotationView to visually represent an annotation on the map. For more information about this, please refer to Recipe 6.4. mapViewWillStartLocatingUser: This method, as its name implies, gets called on the delegate object whenever the map view starts to detect the user’s location. For information about finding a user’s location, please refer to Recipe 6.3. mapView:regionDidChangeAnimated: This method gets called on the delegate object whenever the region displayed by the map is changed. 6.3 Pinpointing the Location of a Device Problem You want to find the latitude and longitude of a device. Solution Use the CLLocationManager class: if ([CLLocationManager locationServicesEnabled]){ self.myLocationManager = [[CLLocationManager alloc] init]; self.myLocationManager.delegate = self; self.myLocationManager.purpose = @"To provide functionality based on user's current location."; [self.myLocationManager startUpdatingLocation]; } else { /* Location services are not enabled. Take appropriate action: for instance, prompt the user to enable the location services */ NSLog(@"Location services are not enabled"); } 436 | Chapter 6: Core Location and Maps In this code, myLocationManager is a property of type CLLocationManager. The current class is also the delegate of the location manager in this sample code. Discussion The Core Location framework in the SDK provides functionality for programmers to be able to detect the current spatial location of an iOS device. Because in iOS, the user is allowed to disable location services using the Settings, before instantiating an object of type CLLocationManager, it is best to first determine whether the location services are enabled on the device. The delegate object of an instance of CLLocationManager must conform to the CLLocationManagerDelegate protocol. This is how we will declare our location manager object in the .h file of a view controller (the object creating an instance of CLLocationManager does not necessarily have to be a view controller): #import <UIKit/UIKit.h> #import <CoreLocation/CoreLocation.h> @interface Pinpointing_the_Location_of_a_DeviceViewController : UIViewController <CLLocationManagerDelegate> @property (nonatomic, strong) CLLocationManager *myLocationManager; @end The implementation of our view controller is as follows: #import "Pinpointing_the_Location_of_a_DeviceViewController.h" @implementation Pinpointing_the_Location_of_a_DeviceViewController @synthesize myLocationManager; - (void)didReceiveMemoryWarning{ [super didReceiveMemoryWarning]; } - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{ /* We received the new location */ NSLog(@"Latitude = %f", newLocation.coordinate.latitude); NSLog(@"Longitude = %f", newLocation.coordinate.longitude); } 6.3 Pinpointing the Location of a Device | 437 - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{ /* Failed to receive user's location */ } - (void)viewDidLoad { [super viewDidLoad]; if ([CLLocationManager locationServicesEnabled]){ self.myLocationManager = [[CLLocationManager alloc] init]; self.myLocationManager.delegate = self; self.myLocationManager.purpose = @"To provide functionality based on user's current location."; [self.myLocationManager startUpdatingLocation]; } else { /* Location services are not enabled. Take appropriate action: for instance, prompt the user to enable the location services */ NSLog(@"Location services are not enabled"); } } - (void) viewDidUnload{ [super viewDidUnload]; [self.myLocationManager stopUpdatingLocation]; self.myLocationManager = nil; } - (BOOL)shouldAutorotateToInterfaceOrientation :(UIInterfaceOrientation)interfaceOrientation{ return YES; } @end The startUpdateLocation instance method of CLLocationManager reports the success or failure of retrieving the user’s location to its delegate through the location Manager:didUpdateToLocation:fromLocation: and locationManager:didFailWithError: methods of its delegate object, in that order. The locationServicesEnabled class method of CLLocationManager is available in SDK 4.0 and later. 438 | Chapter 6: Core Location and Maps [...]... provided by the Map Kit framework, as shown in Figure 6- 6 6. 6 Displaying Custom Pins on a Map View | 451 Figure 6- 6 A custom image displayed on a map view 6. 7 Converting Longitude and Latitude to a Meaningful Address Problem You have the latitude and longitude of a spatial location and you want to retrieve the address of this location 452 | Chapter 6: Core Location and Maps Solution The process of retrieving... :(UIInterfaceOrientation)interfaceOrientation{ return YES; } @end And the results are shown here: 448 | Chapter 6: Core Location and Maps Figure 6 -5 A pin with an alternative color displayed on a map view 6. 6 Displaying Custom Pins on a Map View Problem Instead of the default iOS SDK pins, you would like to display your own images as pins on a map view 6. 6 Displaying Custom Pins on a Map View | 449 Solution Load an arbitrary image... (BOOL)shouldAutorotateToInterfaceOrientation :(UIInterfaceOrientation)interfaceOrientation{ return YES; } @end Figure 6- 4 depicts the output of the program when run in iPhone Simulator 6. 4 Displaying Pins on a Map View | 441 Figure 6- 4 A built-in pin dropped on a map See Also XXX 442 | Chapter 6: Core Location and Maps 6 .5 Displaying Pins with Different Colors on a Map View Problem The default color for pins dropped on... you have a working and active network connection: Found 1 placemark(s) Longitude = -122.8411 35 Latitude = 38.410373 See Also XXX 4 56 | Chapter 6: Core Location and Maps CHAPTER 7 Implementing Gesture Recognizers 7.0 Introduction Gestures are combination of touch events An example of gestures is in the default iOS Photo application that allows the user to zoom into and out of a photo using two fingers... @synthesize myGeocoder; 6. 8 Converting Meaningful Addresses to Longitude and Latitude | 455 And now we will go ahead and implement our code to geocode an address: - (void)didReceiveMemoryWarning{ [super didReceiveMemoryWarning]; // Release any cached data, images, etc that aren't in use } - (void)viewDidLoad{ [super viewDidLoad]; /* We have our address */ NSString *oreillyAddress = @"10 05 Gravenstein Highway... reusableIdentifierforPinColor :(MKPinAnnotationColor)paramColor{ NSString *result = nil; switch (paramColor){ case MKPinAnnotationColorRed:{ result = REUSABLE_PIN_RED; break; 6 .5 Displaying Pins with Different Colors on a Map View | 4 45 } case MKPinAnnotationColorGreen:{ result = REUSABLE_PIN_GREEN; break; } case MKPinAnnotationColorPurple:{ result = REUSABLE_PIN_PURPLE; break; } } return result; } - (id)... requests successfully The reverse geocoded values are reported to the completion handler block that is passed to the reverseGeocodeLocation:completionHan dler: method See Also XXX 454 | Chapter 6: Core Location and Maps 6. 8 Converting Meaningful Addresses to Longitude and Latitude Problem You have an address of a location and you want to find the spatial location (longitude, latitude) of that address... UIViewAutoresizingFlexibleHeight; /* Add it to our view */ [self.view addSubview:self.myMapView]; /* This is just a sample location */ CLLocationCoordinate2D location; location.latitude = 50 .8219 169 2907181; location.longitude = -0.13811 767 101287842; /* Create the annotation using the location */ MyAnnotation *annotation = [[MyAnnotation alloc] initWithCoordinates:location title:@"My Title" subTitle:@"My Sub Title"];... UIViewAutoresizingFlexibleHeight; /* Add it to our view */ [self.view addSubview:self.myMapView]; /* This is just a sample location */ CLLocationCoordinate2D location = CLLocationCoordinate2DMake (50 .8219 169 2907181, -0.13811 767 101287842); /* Create the annotation using the location */ MyAnnotation *annotation = [[MyAnnotation alloc] initWithCoordinates:location title:@"My Title" subTitle:@"My Sub Title"]; /*... recognizers There are six gesture recognizers in iOS SDK 5: • • • • • • Swipe Rotation Pinch Pan Long press Tap The basic framework for handling a gesture through a built-in gesture recognizer is as follows: 1 Create an object of the right data type for the gesture recognizer you want 2 Add this object as a gesture recognizer to the view that will receive the gesture 457 3 Write a method that is called when . shown in Fig- ure 6- 1. 3. Now select the Build Phases tab on the top (Figure 6- 1). 4. Expand the Link Binary With Libraries box (Figure 6- 1) and press the + button. 429 Figure 6- 1. Selecting the. YES; } @end Figure 6- 4 depicts the output of the program when run in iPhone Simulator. 6. 4 Displaying Pins on a Map View | 441 Figure 6- 4. A built-in pin dropped on a map See Also XXX 442 | Chapter 6: Core. or hybrid. In this example, we are using the satellite map type (see Figure 6- 3). 6. 1 Creating a Map View | 433 Figure 6- 3. A satellite map view We can change the visual representation type of