2015年7月30日 星期四

iOS筆記:Core Location & MapKit(1)

Framework for managing location and heading! No user-interface. Basic object is CLLocation

@propertys: coordinate, altitude, horizontal/verticalAccuracy, timestamp, speed, course!

基本宣告

@property (readonly) CLLocationCoordinate2D coordinate;
 typedef {
CLLocationDegrees latitude; # a double
CLLocationDegrees longitude; # a double 
} CLLocationCoordinate2D;

@property (readonly) CLLocationDistance altitude; # meters

The more accuracy you request, the more battery will be used!
Device “does its best” given a specified accuracy request.

How close to that latitude/longitude is the actual location?

@property (readonly) CLLocationAccuracy horizontalAccuracy; # in meters 
@property (readonly) CLLocationAccuracy verticalAccuracy; # in meters 

A negative value means the coordinate or altitude (respectively) is invalid.

kCLLocationAccuracyBestForNavigation // phone should be plugged in to power source
kCLLocationAccuracyBest
kCLLocationAccuracyNearestTenMeters
kCLLocationAccuracyHundredMeters
kCLLocationAccuracyKilometer
kCLLocationAccuracyThreeKilometers

@property (readonly) CLLocationSpeed speed; # in meters/second
@property (readonly) CLLocationDirection course; # in degrees, 0 is north, clockwise
@property (readonly) NSDate *timestamp;

- (CLLocationDistance)distanceFromLocation:(CLLocation *)otherLocation; // in meters

How do you get a CLLocation?

Almost always from a CLLocationManager (sent to you via its delegate).

General approach to using it:

  1. Check to see if the hardware you are on/user supports the kind of location updating you want.
  2. Create a CLLocationManager instance and set the delegate to receive updates.
  3. Configure the manager according to what kind of location updating you want.
  4. Start the manager monitoring for location changes.

Checking to see what your hardware can do!
+ (CLAuthorizationStatus)authorizationStatus; // Authorized, Denied or Restricted (parental, enterprise)
+ (BOOL)locationServicesEnabled; // user has enabled (or not) location services for your application
+ (BOOL)significantLocationChangeMonitoringAvailable;
+ (BOOL)isMonitoringAvailableForClass:(Class)regionClass; //[CLBeacon/CLCircularRegionclass]
+ (BOOL)isRangingAvailable; // device can tell how far it is from beacons!

You can also limit updates to only occurring if the change in location exceeds a certain distance .

@property CLLocationDistance distanceFilter;

Starting and stopping normal position monitoring!

- (void)startUpdatingLocation;
- (void)stopUpdatingLocation;

Be sure to turn updating off when your application is not going to consume the changes!!
Get notified via the CLLocationManager’s delegate! -

(void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations; # of CLLocation! 

Similar API for heading (CLHeading, et. al.)

It is possible to receive these kinds of updates in the background.

There are 2 ways to get location notifications.
1. Significant location change monitoring in CLLocationManager, this works even if your application is not running.You will get launched and your Application Delegate will receive the message!

- (void)startMonitoringSignificantLocationChanges;
- (void)stopMonitoringSignificantLocationChanges;

#function
application:didFinishLaunchingWithOptions: #with an options dictionary that will contain UIApplicationLaunchOptionsLocationKey
  1. Region-based location monitoring in CLLocationManager!
    一個圓形半徑的範圍, 如果用戶進入就會發送訊息.
- (void)startMonitoringForRegion:(CLRegion *)region; # CLCircularRegion/CLBeaconRegion - (void)stopMonitoringForRegion:(CLRegion *)region;

Get notified via the CLLocationManager’s delegate!

- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region; 
- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region;
- (void)locationManager:(CLLocationManager *)manager monitoringDidFailForRegion:(CLRegion *)region
withError:(NSError *)error;

To be a beacon is a bit more involved!

Need to check out CBPeripheralManager (Core Bluetooth Framework).

Map Kit

User interface of location.
enter image description here

enter image description here

enter image description here

enter image description here

To use MKMapView: Create with alloc/init or drag from object palette in Xcode! Displays an array of objects which implement MKAnnotation

@property (readonly) NSArray *annotations; # contains id <MKAnnotation> objects ! 

MKAnnotation protocol

@protocol MKAnnotation <NSObject>
@property (readonly) CLLocationCoordinate2D coordinate;
@optional
@property (readonly) NSString *title; 
@property (readonly) NSString *subtitle;
@end

#require
typedef { 
    CLLocationDegrees latitude; 
    CLLocationDegrees longitude;
} CLLocationCoordinate2D;

Note that the annotations property is readonly, so …

@property (readonly) NSArray *annotations; # contains id <MKAnnotation> objects 

Must add/remove annotations explicitly

  • (void)addAnnotation:(id )annotation;
  • (void)addAnnotations:(NSArray *)annotations;
  • (void)removeAnnotation:(id )annotation;
  • (void)removeAnnotations:(NSArray *)annotations;

What happens when you touch on an annotation (e.g. the pin)?

Depends on the MKAnnotationView that is associated with the annotation (more on this later). By default, nothing happens, but if canShowCallout is YES in the MKAnnotationView, then
a little box will appear showing the annotation’s title and subtitle.
And this little box (the callout) can be enhanced with left/rightCalloutAccessoryViews.

How are MKAnnotationViews created & associated w/annotations?!

Very similar to UITableViewCells in a UITableView(CellForRowAtIndex 給section and row 就得到一個cell ).

enter image description here

Using didSelectAnnotationView: to load up callout accessories

- (void)mapView:(MKMapView *)sender didSelectAnnotationView:(MKAnnotationView *)aView 
{
    if ([aView.leftCalloutAccessoryView isKindOfClass:[UIImageView class]]) {
        UIImageView *imageView = (UIImageView *)aView.leftCalloutAccessoryView;
imageView.image = ...; 
#if you do this in a GCD queue, be careful, views are reused! 
    }
}

enter image description here

Controlling the region (part of the world) the map is displaying

@property MKCoordinateRegion region; 
typedef struct {
    CLLocationCoordinate2D center;
    MKCoordinateSpan span; 
} MKCoordinateRegion; 
typedef struct {
    CLLocationDegrees latitudeDelta;
    CLLocationDegrees longitudeDelta; 
}
- (void)setRegion:(MKCoordinateRegion)region animated:(BOOL)animated; # animate

This is a good place to “chain” animations to the map.!
When you display somewhere new in the map that is far away, zoom out, then back in.! This method will let you know when it’s finished zooming out, so you can then zoom in.

- (void)mapView:(MKMapView *)mapView didChangeRegionAnimated:(BOOL)animated;

MKLocalSearch: Searching for places in the world

Can search by “natural language” strings asynchronously (uses the network)

MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init]; 
request.naturalLanguageQuery = @“Ike’s”;
request.region = ...;
MKLocalSearch *search = [[MKLocalSearch alloc] initWithRequest:request];
[search startWithCompletionHandler:^(MKLocalSearchResponse *response, NSError *error) {
  # response contains an array of MKMapItem which contains MKPlacemark 
}];

You can open one of these MapItem in the Maps app

- (BOOL)openInMapsWithLaunchOptions:(NSDictionary *)options; // options like region, show traffic

enter image description here

Add overlays to the MKMapView and it will later ask you for a renderer to draw the overlay.

- (void)addOverlay:(id <MKOverlay>)overlay level:(MKOverlayLevel)level;

Level is (currently) either AboveRoads or AboveLabels (over everything but annotation views).

- (void)removeOverlay:(id <MKOverlay>)overlay;

Built-in Overlays and Renderers for numerous shapes …

MKCircleRenderer
MKPolylineRenderer
MKPolygonRenderer
MKTileOverlayRenderer #can also be used to replace the map data from Apple

Embed Segues

Drag out a Container View from the object palette into the scene you want to embed it in. Automatically sets up an “Embed Segue” from container VC to the contained VC.

沒有留言:

張貼留言