1. Trang chủ
  2. » Công Nghệ Thông Tin

Tài liệu Lập trình iPhone part 14 pptx

12 292 0
Tài liệu được quét OCR, nội dung có thể không chính xác
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Tài Liệu Lập Trình iPhone Part 14
Trường học University of Information Technology
Chuyên ngành iPhone Programming
Thể loại Tài liệu
Định dạng
Số trang 12
Dung lượng 288,24 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

In order to interact with Core Location, we need to create an instance of the Location Manager, like this: CLLocationManager *locationManager = [[CLLocationManager alloc] init]; This cr

Trang 1

Where Am I?

Finding Your Way

with Core Location

our iPhone has the ability to determine where in the world it is using a frame-

work called Core Location There are actually three technologies that Core

Location can leverage to do this: GPS, cell tower triangulation, and Wi-Fi

Positioning Service (WPS) GPS is the most accurate of the three but is not

available on first-generation iPhones GPS reads microwave signals from

multiple satellites to determine the current location Cell tower triangulation

determines the current location by doing a calculation based on the locations

of the cell towers in the phone's range Cell tower triangulation can be fairly accurate in cities and other areas with a high cell tower density but becomes

less accurate in areas where there is a greater distance between towers The last option, WPS, uses the IP address from iPhone’s Wi-Fi connection to make

a guess at your location by referencing a large database of known service

providers and the areas they service WPS is imprecise and can be off by

many miles

All three methods put a noticeable drain on iPhone's battery, so keep that in mind when using Core Location Your application shouldn't poll for location any more often than is absolutely necessary When using Core Location, you

have the option of specifying a desired accuracy By carefully specifying the

absolute minimum accuracy level you need, you can prevent unnecessary

battery drain

The technologies that Core Location depends on are hidden from your appli-

cation We don't tell Core Location whether to use GPS, triangulation, or WPS.

Trang 2

We just tell it how accurate we would like it to be, and it will decide which technologies give

it the best chance to fulfill your request

The Location Manager

The Core Location API is actually fairly easy to work with The main class we'll work with is

CLLocationManager, usually referred to as the Location Manager In order to interact with Core Location, we need to create an instance of the Location Manager, like this:

CLLocationManager *locationManager = [[CLLocationManager alloc] init];

This creates an instance of the Location Manager for us, but it doesn’t actually start polling for our

location We create a delegate and assign it to the Location Manager The Location Manager calls our delegate method when the location information is available This may take some time, even

a few seconds Our delegate must conform to the CLLocati onManagerDelegate protocol Setting the Desired Accuracy

After you set the delegate, you also want to set the requested accuracy As we said before, don't specify a degree of accuracy any greater than you absolutely need If you're writing

an application that just needs to know which state or country the phone is in, don’t specify

a high level of precision Remember, the more accuracy you demand of Core Location, the

more juice you're likely to use Also, keep in mind that there is no guarantee that you will get

the level of accuracy that you have requested

Here’s an example of setting the delegate and requesting a specific level of accuracy:

locationManager.delegate = self;

locationManager.desiredAccuracy = kCLLocationAccuracyBest;

The accuracy is set using a CLLocationAccuracy value, a type that’s defined as a double The value is in meters, so if you specify a desi redAccuracy of 10, you're telling Core Location that you want it to try to determine the current location within 10 meters, if possible Specifying kCLLocationAccuracyBest, as we did previously, tells Core Location to use the most accurate

method that’s currently available In addition to kCcLLocationAccuracyBest, you can also

use kCLLocationAccuracyNearestTenMeters, kCLLocationAccuracyHundredMeters, kCLLocationAccuracyKi lometer, and kCLLocationAccuracyThreeKi lometers

Setting the Distance Filter

By default, the Location Manager will notify the delegate of any detected change in location By specifying a distance filter, you are telling Location Manager not to notify you for every change

Trang 3

and to only notify you when the location changes more than a certain amount Setting up a dis-

tance filter can reduce the amount of polling that your application does Distance filters are also

set in meters Specifying a distance filter of 1000 tells the Location Manager not to notify the

delegate until the iPhone has moved at least 1,000 meters from its previously reported position Here’s an example:

locationManager.distanceFilter = 1000.0f;

If you ever want to return the Location Manager to the default setting of no filter, you can use the constant kCLDi stanceFi 1 terNone, like this:

locationManager.distanceFilter = kCLDistanceFiIlterNone;

Starting the Location Manager

When you’re ready to start polling for location, you tell the Location Manager to start, and

it will then go off and do its thing and then call a delegate method when it has determined

the current location Until you tell it to stop, it will continue to call your delegate method whenever it senses a change that exceeds the current distance filter Here’s how you start the location manager:

[locationManager startUpdatingLocation];

Using the Location Manager Wisely

If you only need to determine the current location and have no need to continuously poll

for location, you should have your location delegate stop the location manager as soon as

it gets the information your application needs If you need to continuously poll, make sure you stop polling as soon as you possibly can Remember, as long as you are getting updates from the Location Manager, you are putting a strain on the user's battery To tell the Location Manager to stop sending updates to its delegate, call stopUpdatingLocation, like this:

[locationManager stopUpdatingLocation];

The Location Manager Delegate

The location manager delegate must conform to the CLLocationManagerDe legate protocol, which defines two methods, both of which are optional One of these methods is called by the

Location Manager when it has determined the current location or when it detects a change in location The other method is called when the Location Manager encounters an error.

Trang 4

Getting Location Updates

When the Location Manager wants to inform its delegate of the current location, it calls

the locationManager :didUpdateToLocation: fromLocation: method This method has

second is a CLLocation object that defines the current location of the iPhone, and the third

is a CLLocation object that defines the previous location from the last update The first time this method is called, the previous location object will be ni1

Getting Latitude and Longitude Using CLLocation

Location information is passed from the Location Manager using instances of the CLLocation

and longitude are stored in a property called coordinate To get the latitude and longitude in degrees, do this:

CLLocationDegrees latitude = theLocation.coordinate latitude;

CLLocationDegrees longitude = theLocation.coordinate longitude;

The CLLocati on object can also tell you how confident the Location Manager is in its lati-

a circle with the coordinate as its center The larger the value in horizontalAccuracy, the

less certain Core Location is of the location A very small radius indicates a high level of con-

fidence in the determined location

You can see a graphic representation of horizontalAccuracy in the Maps application (see

Figure 14-1) The blue circle shown in Maps uses horizontalAccuracy for its radius when

it detects your location The Location Manager thinks you are at the center of that circle

If you're not, you're almost certainly somewhere inside the blue circle A negative value in

horizontalAccuracy is an indication that you cannot rely on the values in coordinate for

some reason

The CLLocation object also has a property called al ti tude that can tell you how many

meters above or below sea level you are:

CLLocationDistance altitude = theLocation.altitude

Each CLLocation object maintains a property called verticalAccuracy that is an indication

of how confident Core Location is in its determination of altitude The value in altitude could

be off by as many meters as the value in verticalAccuracy, and if the verticalAccuracy value is negative, Core Location is telling you it could not determine a valid altitude

CLLocation objects also have a timestamp that tells when the Location Manager made the location determination.

Trang 5

In addition to these properties, CLLocation also has a use-

ful instance method that will let you determine the distance

between two CLLocation objects The method is called

CLLocationDistance distance = [fromLocation=™

getDistanceFrom:toLocation] ;

The preceding line of code will return the distance between

two CLLocation objects, fromLocation and toLocation

distance calculation that ignores the altitude property and cal-

culates the distance as if both points were at sea level For most

purposes, a great-circle calculation will be more than sufficient,

but if you do need to take altitude into account when calculat-

Figure 14-1 The Maps appli- cation uses Core Location to

If Core Location is not able to determine your current loca- determine your current loca-

tion, it will call a second delegate method named location tion The blue circle is a visual

error is that the user denies access Location Manager use has

to be authorized by the user, so the first time your application

goes to determine the location, an alert will pop up on the

screen asking the user if it’s OK for the current program

to access your location (see Figure 14-2)

Error Notifications

If the user clicks the Don't Allow button, your delegate will

be notified of the fact by the Location Manager using the

locationManager:didFailwithError: with an error code

‘WhereAm!” would like to use

other error code supported by Location Manager is si ei cà

kCLErrorLocationUnknown, which indicates that Core

Location was unable to determine the location but that it

will keep trying The kCcLErrorDenied error generally indi-

cates that your application will not be able to access Core

Location any time during the remainder of the current ses-

sion On the other hand, kCLErrorLocationUnknown errors

indicate a problem that may be temporary

Figure 14-2 Location Manager access has to be approved by the user

Trang 6

OTE

When working in the simulator, you will not be prompted for access to Core Location, and location will be determined using a super secret algorithm kept in a locked vault buried deep beneath Apple headquarters

in Cupertino

Trying Out Core Location

Let’s build a small application to detect the iPhone's current

location and the total distance traveled while the program

Horizontal Accuracy:

application template, and call the project WhereAml

Expand the Classes and Resources folders, and single-click

WhereAm|ViewController.h Make the following changes,

which we'll discuss in a moment:

Distance Traveled:

#import <UIKit/UIKit.h>

#import <CoreLocation/CoreLocation.h>

@interface WhereAmIViewControl ler

UIViewController <CLLocationManagerDelegate> {

CLLocat ionManager *locationManager; Figure 14-3 The WhereAm|

application in action This screenshot was taken in the simulator Notice that the vertical accuracy is a negative number, which tells us it couldn't determine the altitude

CLLocation *startingPoint;

TBOutTet UILabel *latitudeLabel ;

TBOutTet UILabel *longitudeLabel ;

TBOutTet UILabel *horizontalAccuracyLabel ;

TBOutTet UILabel *altitudeLabel ;

TBOutTet UTLabeT *verticaTlAccuracyLabel ;

TBOutTet UILabel *distanceTraveledLabel ;

}

@property (retain, nonatomic) CLLocationManager *locationManager ;

@property (retain, nonatomic) CLLocation *startingPoint ;

@property (retain, nonatomic) UILabel *latitudeLabel ;

@property (retain, nonatomic) UILabel *longitudeLabel ;

@property (retain, nonatomic) UILabel *horizontalAccuracyLabel;

@property (retain, nonatomic) UILabel *altitudeLabel ;

@property (retain, nonatomic) UILabel *verticalAccuracyLabel;

@property (retain, nonatomic) UILabel *distanceTraveled;

@end

Trang 7

The first thing to notice is that we’ve included the Core Location header files Core Location

is not part of the UIKit, so we need to include the header files manually Next, we conform

this class to the CLLocati onManagerDelegate method so that we can receive location infor- mation from the Location Manager

After that, we declare a CLLocationManager pointer, which will be used to hold the instance

of the Core Location we create We also declare a pointer to a CLLocati on, which we will set

to the location we receive in the first update from the location manager This way, if the user has our program running and moves far enough to trigger an update, we'll be able to calcu- late how far our user moved

The remaining instance variables are all outlets that will be used to update labels on the user interface

Double-click WhereAm!ViewController.xib to open Interface Builder Using Figure 14-3 as your guide, drag twelve Labels over from the library to the View window Six of them should

be placed on the left side of the screen, right justified, and made bold The six bold labels should be given the values Latitude:, Longitude:, Horizontal Accuracy, Altitude:, Vertical Accu-

racy:, and Distance Traveled:, The other six should be left-justified and placed next to each

of the bold labels Each of the labels on the right side should be connected to the appropri- ate outlet we defined in the header file earlier Once you have all six attached to outlets, double-click each one in turn, and delete the text it holds Save and go back to Xcode Single-click WhereAm!ViewController.m, and make the following changes:

#import "WhereAmIViewController.h"

@implementation WhereAmIViewController

@synthesize locationManager ;

@synthesize startingPoint;

@synthesize latitudeLabel;

@synthesize longitudeLabel ;

@synthesize horizontalAccuracyLabel ;

@synthesize altitudeLabel;

@synthesize verticalAccuracyLabel ;

@synthesize distanceTraveled;

#pragma mark -

- (void)viewDidLoad {

self.locationManager = [[CLLocationManager alloc] init];

locationManager.delegate = self;

locationManager.desiredAccuracy = kCLLocationAccuracyBest ;

[locationManager startUpdatingLocation] ;

}

- (BOOL) shouldAutorotateToInterfaceOrientation:

(UIInterfaceOrientation)interfaceOrientation {

Trang 8

// Return YES for supported orientations

return CinterfaceOrientation == UIInterfaceOrientationPortrait);

(void) didReceiveMemoryWarning {

[super didReceiveMemoryWarning];

// Releases the view if it doesn't have a superview

// Release anything that's not essential, such as cached data

(void)dealloc {

[locationManager release];

[startingPoint release];

[latitudeLabel release];

LlongitudeLabel release];

[horizontalAccuracyLabel release];

[altitudeLabel release];

[verticalAccuracyLabel release];

[distanceTraveled release] ;

[super dealloc];

}

#pragma mark -

#pragma mark CLLocationManagerDelegate Methods

- (void) locationManager: (CLLocationManager *)manager

didUpdateToLocation: (CLLocation *)newLocation

fromLocation: (CLLocation *)oldLocation {

if (startingPoint == nil)

self.startingPoint = newLocation;

NSString *latitudeString = [[NSString alloc] initWithFormat:@"%g°",

newLocation.coordinate latitude];

latitudeLabel.text = latitudeString;

[latitudeString release];

NSString *longitudeString = [[NSString alloc] initWithFormat :@"%g°",

newLocation.coordinate longitude];

longitudeLabel.text = longitudeString;

LlongitudeString release];

NSString *horizontalAccuracyString = [[NSString alloc]

initWithFormat:@"%gm",

newLocation.horizontal Accuracy];

horizontalAccuracyLabel.text = horizontalAccuracyString;

[horizontalAccuracyString release];

NSString *altitudeString = [[NSString alloc] initWithFormat:@"%gm",

Trang 9

newLocation.altitude];

altitudeLabel.text = altitudeString;

[altitudeString release];

NSString *verticalAccuracyString = [[NSString alloc]

initWithFormat:@"%gm",

newLocation.verticalAccuracy];

verticalAccuracyLabel.text = verticalAccuracyString;

[verticalAccuracyString release];

CLLocationDistance distance = [newLocation

getDistanceFrom: startingPoint] ;

NSString *distanceString = [[NSString alloc]

initWithFormat:@"%gm", distance];

distanceTraveledLabel.text = distanceString;

[distanceString release];

}

- (void) locationManager: (CLLocationManager *)manager

didFailWithError: (NSError *)error {

NSString *“errorType = (error.code == kCLErrorDenied) ?

@"Access Denied" : @"Unknown Error";

UIAlertView “alert = [[UIAlertView alloc]

initWithTitle:@"Error getting Location"

message:errorType delegate:nil cancelButtonTitle:@"Okay"

otherButtonTitles:nil];

[alert show];

[alert release];

}

@end

In the viewDidLoad method, we allocate and initialize a CLLocati onManager instance, assign our controller class as the delegate, set the desired accuracy to the best available, and then tell our Location Manager instance to start giving us location updates:

- (void)viewDidLoad {

self locationManager = [[CLLocationManager alloc] init];

locationManager.delegate = self;

locationManager.desiredAccuracy = kCLLocationAccuracyBest;

[locationManager startUpdatingLocation] ;

Trang 10

Updating Location Manager

Since this class designated itself as the location manager’s delegate, we know that location updates will come in to this class if we implement the delegate method locationmanager:

di dUpdateToLocation: fromLocation:, so let’s look at our implementation of that method

The first thing we do in that method is check to see if startingPoint is ni 1 If it is, then this update is the first one from the Location Manager, and we assign the current location to our

startingPoint property

if CstartingPoint == nil)

self.startingPoint = newLocation;

After that, we update the first six labels with values from the CLLocation object passed in

the newLocation argument:

NSString *latitudeString = [[NSString alloc] initWithFormat:@"%g°", newLocation coordinate latitude];

latitudeLabel.text = latitudeString;

[latitudeString release];

NSString *longitudeString = [[NSString alloc] initWithFormat:@"%g°", newLocation coordinate longitude] ;

longitudeLabel.text = longitudeString;

LlongitudeString release];

NSString *horizontalAccuracyString = [[NSString alloc]

ini twithFormat:@"%gm" ,

newLocation.horizontalAccuracy] ;

horizontalAccuracyLabel.text = horizontalAccuracyString;

[horizontalAccuracyString release];

NSString *altitudeString = [[NSString alloc] initWithFormat:@"%gm", newLocation.altitude];

altitudeLabel.text = altitudeString;

[altitudeString release];

NSString *verticalAccuracyString = [[NSString alloc]

ini twithFormat:@"%gm" ,

newLocation.verticalAccuracy];

verticalAccuracyLabel.text = verticalAccuracyString;

[verticalAccuracyString release] ;

TIP

You can type the degree symbol (°) by pressing <> \8

Ngày đăng: 26/01/2014, 10:20