CLLocationManager

2018-10-24  本文已影响26人  ngugg

The object that you use to start and stop the delivery of location-related events to your app.

Overview

You use instances of this class to configure, start, and stop the Core Location services. A location manager object supports the following location-related activities:

Tracking large or small changes in the user’s current location with a configurable degree of accuracy.

Reporting heading changes from the onboard compass. (iOS only)

Monitoring distinct regions of interest and generating location events when the user enters or leaves those regions.

Deferring the delivery of location updates while the app is in the background. (iOS only)

Reporting the range to nearby beacons.

When you are ready to use location services, follow these steps:

  1. Check to see if your app is authorized to use location services and request permission if your app's authorization status is not yet determined, as described in Requesting Permission to Use Location Services.
  1. Check to see if the appropriate location services are available for you to use, as described in Determining the Availability of Location Services.
    检查是否有适合您使用的位置服务,如确定位置服务的可用性中所述。

  2. Create an instance of the CLLocationManager class and store a strong reference to it somewhere in your app.

  1. Assign a custom object to the delegate property. This object must conform to the CLLocationManagerDelegate protocol.
  1. Configure the properties related to the service you intend to use. For example, when getting location updates, always configure the distanceFilter and desiredAccuracyproperties.
  1. Call the appropriate method to start the delivery of events.

For the services you use, configure any properties associated with that service accurately. Core Location manages power aggressively by turning off hardware when it is not needed. For example, setting the desired accuracy for location events to one kilometer gives the location manager the flexibility to turn off GPS hardware and rely solely on the WiFi or cell radios, which can lead to significant power savings.

All location- and heading-related updates are delivered to the associated delegate object, which is a custom object that you provide. For information about the delegate methods you use to receive events, see CLLocationManagerDelegate.

CLLocationManagerDelegate

The methods that you use to receive events from an associated location manager object.

Overview

The location manager calls the methods of this delegate to report location-related events to your app. Implement this protocol in an app-specific object and use the methods to update your app. For example, you might use the current location to update the user's position on a map or you might return search results relevant only to the user's current location.

Important

Always implement the methods for handling any potential failures in addition to the methods for receiving location-related data.

Assign your delegate object to the delegate property of the CLLocationManager object before starting any services. Core Location may report a cached value to your delegate immediately after you start the service, followed by a more current value later. Check the time stamp of any data objects you receive before using them.

The methods of your delegate object are called from the thread in which you started the corresponding location services. That thread must itself have an active run loop, like the one found in your application’s main thread.

Determining the Availability of Location Services

Determine which location services are active and available on the user's device.

Overview

Not all Core Location services are available on every device, and services may be temporarily unavailable in certain circumstances:
并非所有Core Location服务都可在每台设备上使用,并且在某些情况下服务可能暂时不可用:

Before using any specific location service, check the availability of that service using the methods of your CLLocationManager object. Table 1 lists the methods you call and explains any hardware requirements for the corresponding services.

Table 1 Getting the availability of Core Location services

  1. locationEnabled(),Tells whether you can get the geographic coordinate for the user's current location. This service is generally available on all devices. See Getting the User's Location.

    • 告诉您是否可以获取用户当前位置的地理坐标。 此服务通常适用于所有设备。 请参阅获取用户的位置。
  2. significantLocationChangeMonitoringAvailable(),Tells whether you can get the user's location using the signficant-change location service. This service requires specific hardware and may not be available on all devices. See Getting the User's Location.

  1. MonitoringAvailable(for:),Tells whether you can use region monitoring to detect entry into or exit from geographic regions or iBeacon regions. Support for geographic region monitoring requires specific hardware and is generally available on all iOS devices. Support for iBeacon region monitoring requires Bluetooth hardware and is generally available on all devices. For information on how to monitor geographic regions, see Monitoring the User's Proximity to Geographic Regions. For information on how to monitor iBeacon regions, see Determining the Proximity to an iBeacon.
  1. headingAvailable(),Tells whether the device is able to provide compass-related headings. This service requires the presence of a magnetometer. See Getting Heading and Course Information.
  1. isRangingAvailable(),Tells whether you can obtain the relative distance to a nearby iBeacon. This service requires Bluetooth hardware and is generally available on all devices. See Determining the Proximity to an iBeacon.

Listing 1 shows how to check for the availability of the standard location service. Based on the availability of those services, you would enable or disable features of your app accordingly.

Listing 1 Checking for the availability of the standard location service

func checkForLocationServices() {
    if CLLocationManager.locationServicesEnabled() {
        // Location services are available, so query the user’s location.
    } else {
        // Update your app’s UI to show that the location is unavailable.
    }
}

If you try to start a service that is unavailable, the CLLocationManager object calls one of the failure-related methods of its delegate. For example, if region monitoring is unavailable, it calls the locationManager(_:monitoringDidFailFor:withError:) method.

Note
Apps should fail gracefully and offer other useful capabilities when services are not available. If the absence of a service renders your app useless, you can indicate the requirement of that service in your app's Info.plist. For more information, see Requiring the Presence of Specific Location Services.

Requiring the Presence of Specific Location Services

Declare the location services that your app requires.

Overview

If your app requires the presence of specific location-related hardware, you must declare those requirements in the app’s Info.plist file. For new iOS projects, Xcode includes the Required device capabilities key in the Info.plist file. The value of this key is an array of strings, each of which specifies a type of hardware that must be present on the device. The App Store prevents the installation of apps on devices that do not support the required hardware. You can add the following strings to indicate that you require the specified hardware or services:

Table 1 Keys for requiring location services

  1. key: location-services, description: Include this key if your app requires location services. Always include it if you also include the gps or magnetometer key.
  1. key: gps, description: Include this key if your app requires GPS-level precision for locations, or if you require course information. Navigation apps typically include this key in their Info.plist.
  1. key: magnetometer, description: Include this key if your app uses heading information, which requires the presence of a magnetometer.

If your app is able to function without the specified capabilities, do not include them as requirements.

Choosing the Authorization Level for Location Services

Choose the appropriate level of access to location data for your app.

Overview

The type of authorization (“when-in-use” or “always”) that you request determines which location services your app can access and when it can use them:

It is recommended that you request only when-in-use authorization whenever possible. If your app requests and receives when-in-use authorization, you can make a separate request for always authorization later. (Apps may make only one request for always authorization.) Even if you request always authorization, the user has the option of granting your app when-in-use authorization instead. So you must always be prepared to run with when-in-use authorization.

Important
Always request authorization at the point where you the user needs location services to perform a task, such as when the user activates a feature that requires the current location. Requesting authorization may display an alert to the user. If it's not clear to the user why your app is using location services, the user may deny your request.

Table 1 lists the location services available for each type of authorization.

Table 1 Authorizations supported by the location services

image.png

After making an authorization request, it is safe to start location services before your request is resolved. However, location services do not deliver any data until the authorization status changes to CLAuthorizationStatus.authorizedAlways or CLAuthorizationStatus.authorizedWhenInUse. Implement the locationManager(_:didChangeAuthorization:) method in your location manager delegate to be notified when your app's authorization status changes.

releated:
Requesting When-In-Use Authorization
https://developer.apple.com/documentation/corelocation/choosing_the_authorization_level_for_location_services/requesting_when-in-use_authorization
Requesting Always Authorization https://developer.apple.com/documentation/corelocation/choosing_the_authorization_level_for_location_services/requesting_always_authorization

Requesting When-In-Use Authorization

Request authorization to use location services only when your app is running.

Overview

To configure when-in-use authorization for location services, follow these steps (Listing 1demonstrates steps 2 and 3.):

  1. Add the NSLocationWhenInUseUsageDescription key to your app's Info.plistfile. (Xcode displays this key as "Privacy - Location When In Use Usage Description" in the Info.plist editor.)
  1. Create and configure your CLLocationManager object.
  1. Call the requestWhenInUseAuthorization() method of your CLLocationManagerobject prior to starting any location services.

Important
You must add the NSLocationWhenInUseUsageDescription key to your app's Info.plist file. If that key is not present, authorization requests fail immediately.

Request authorization at the point where you need location services. For example, wait until the user activates a feature of your app that requires location data. Don't request authorization at launch time unless you need the user's location immediately or your app was launched in the background by the system to handle a location update.

Request When-In-Use Authorization

Listing 1 shows how you might request when-in-use authorization before starting your app's location-related services, by calling the requestWhenInUseAuthorization() method. You need to request authorization only when your app's authorization status is not determined. If your app's authorization status is already determined, you can simply start the services that you need.

Listing 1 Requesting authorization to use location services

let locationManager = CLLocationManager()
func enableBasicLocationServices() {
   locationManager.delegate = self
        
   switch CLLocationManager.authorizationStatus() {
      case .notDetermined:
         // Request when-in-use authorization initially
         locationManager.requestWhenInUseAuthorization()
         break
            
      case .restricted, .denied:
         // Disable location features
         disableMyLocationBasedFeatures()
         break
            
      case .authorizedWhenInUse, .authorizedAlways:
         // Enable location features
         enableMyWhenInUseFeatures()
         break
      }
   }
}

Respond to Changes in Authorization Status

When you make an authorization request, Core Location processes your request asynchronously and delivers the results to the locationManager(_:didChangeAuthorization:) method of your location manager's delegate object. Use that method to determine whether the user granted or denied your request, and to take any appropriate actions in response.

Listing 2 shows an implementation of the locationManager(_:didChangeAuthorization:) method that enables the app's location-related features when the app receives authorization and disables those features when authorization is denied or restricted for any reason.

Listing 2 Getting changes to the app's authorization

func locationManager(_ manager: CLLocationManager, 
                      didChangeAuthorization status: CLAuthorizationStatus) {
   switch status {
      case .restricted, .denied:
         disableMyLocationBasedFeatures()
         break
            
      case .authorizedWhenInUse:
         enableMyWhenInUseFeatures()
         break
                  
      case .notDetermined, .authorizedAlways:
         break
   }
}

Important
The availability of location services may change at any time. The user can disable location services in the system settings, either for your app specifically or for all apps. Location services are also disabled when a device enters Airplane mode, and they may resume when the device leaves Airplane mode. If your app is running (either in the foreground or in the background) when the availability status changes, the system calls your locationManager(_:didChangeAuthorization:) method to notify you of the change.

Requesting Always Authorization

Request authorization to use location services at any time.

Overview

To configure always authorization for location services, follow these steps (Listing 1demonstrates steps 3-5):
要始终配置位置服务的授权,请按照下列步骤操作(清单1演示步骤3-5):

  1. Add the NSLocationWhenInUseUsageDescription key and the NSLocationAlwaysAndWhenInUseUsageDescription key to your Info.plist file. (Xcode displays these keys as "Privacy - Location When In Use Usage Description" and "Privacy - Location Always and When In Use Usage Description" in the Info.plist editor.)
  1. If your app supports iOS 10 and earlier, add the NSLocationAlwaysUsageDescription key to your Info.plist file. (Xcode displays this key as "Privacy - Location Always Usage Description" in the Info.plist editor.)
  1. Create and configure your CLLocationManager object.
  1. Call the requestWhenInUseAuthorization() initially to enable your app's basic location support.
  1. Call the requestAlwaysAuthorization() method only when the user enables a feature of your app that requires that level of authorization.

Don't request authorization at launch time unless you need the user's location immediately or were launched in the background to receive a location update.

Important
You are required to include the NSLocationWhenInUseUsageDescription and NSLocationAlwaysAndWhenInUseUsageDescription keys in your app's Info.plist file. (If your app supports iOS 10 and earlier, the NSLocationAlwaysUsageDescription key is also required.) If those keys are not present, authorization requests fail immediately.

Enable When-In-Use Authorization Before Always Authorization

Listing 1 shows one way to enable your app's location services initially. If your app's authorization status is already determined, you don't need to request authorizationa gain. If your app's authorization status is not determined, try to limit your initial authorization request to when-in-use authorization. You can request always authorization right away if your app requires the corresponding location services, but be prepared for the user to grant only when-in-use authorization or to deny your request altogether.

Listing 1 Requesting authorization to use location services

let locationManager = CLLocationManager()   
func enableLocationServices() {
   locationManager.delegate = self
        
   switch CLLocationManager.authorizationStatus() {
      case .notDetermined:
         // Request when-in-use authorization initially
         locationManager.requestWhenInUseAuthorization()
         break
            
      case .restricted, .denied:
         // Disable location features
         disableMyLocationBasedFeatures()
         break
            
      case .authorizedWhenInUse:
         // Enable basic location features
         enableMyWhenInUseFeatures()
         break
            
      case .authorizedAlways:
         // Enable any of your app's location features
         enableMyAlwaysFeatures()
         break
      }
   }      
}

Escalate the App's Authorization Level

In iOS 11 and later, if you initially requested only when-in-use authorization, you can call the requestAlwaysAuthorization() method at a later time (as shown in Listing 2) to escalate your app's authorization level. When requesting always authorization, the system displays the usage description string stored in the NSLocationAlwaysAndWhenInUseUsageDescription key of your Info.plist file. The user must then choose whether to grant the request for always authorization or to leave your app with when-in-use authorization. The system lets your app escalate its authorization level only once, displaying an appropriate interface to the user when you do. Subsequent attempts do not display a system interface and do not change your app's authorization level.

Listing 2 Escalating from when-in-use to always authorization

func escalateLocationServiceAuthorization() {
   // Escalate only when the authorization is set to when-in-use
   if CLLocationManager.authorizationStatus() == .authorizedWhenInUse {
      locationManager.requestAlwaysAuthorization()
   }
}

Respond to Changes in Authorization Status

When you request authorization, or when your app's authorization status changes, use the locationManager(_:didChangeAuthorization:) method of your delegate object to process the changes. Listing 3 shows an implementation of that method that enables or disables features based on the app's current authorization level.

Listing 3 Getting changes to the app's authorization

func locationManager(_ manager: CLLocationManager, 
                     didChangeAuthorization status: CLAuthorizationStatus) {   switch status {
      case .restricted, .denied:
         // Disable your app's location features
         disableMyLocationBasedFeatures()
         break
            
      case .authorizedWhenInUse:
         // Enable only your app's when-in-use features.
         enableMyWhenInUseFeatures()
         break
            
      case .authorizedAlways:
         // Enable any of your app's location services.
         enableMyAlwaysFeatures()
         break
            
      case .notDetermined:
         break
   }
}

Important

The availability of location services may change at any time. The user can disable location services in the system settings, either for your app specifically or for all apps. Location services are also disabled when a device enters Airplane mode, and they may resume when the device leaves Airplane mode. If your app is running (either in the foreground or in the background) when the availability status changes, the system calls your locationManager(_:didChangeAuthorization:) method to notify you of the change.

上一篇 下一篇

猜你喜欢

热点阅读