我已经做了几个月的iOS开发,最近我正在开发一个公交应用。
我目前正在模仿公共汽车的运动,并在公共汽车站设置多个注释。出于测试目的,我只设置了一个公共汽车站,并试图监视公共汽车何时进入该区域并退出。
奇怪的是,我的didStartMonitoringForRegion
方法被完美地调用了,但didEnterRegion
和didExitRegion
方法都没有被调用。与此同时,不会调用任何错误。每次我运行这个程序,公共汽车几乎都没有提示我过站。
有人能解释一下为什么会发生这种情况以及如何解决它吗?
// ViewController.swift
// Parta Service
// Created by Emil Shirima on 8/24/15.
// Copyright (c) 2015 Emil Shirima. All rights reserved.
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
@IBOutlet weak var mapView: MKMapView!
let locationManager = CLLocationManager()
var allBusAnnotations = [MKPointAnnotation]()
var summitEastBusStations = [CLLocationCoordinate2D]()
var busStopNames = ["Dix Stadium", "Risman Plaza", "Terrace Drive", "Terrace Drive 2","C-Midway","Theatre Dr.","East Main Street","South Lincoln"]
var radius = 250 as CLLocationDistance
// 0.02 is the best zoom in factor
var mapZoomInFactor : Double = 0.02
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.getBusStop()
self.locationManager.delegate = self
// gets the exact location of the user
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
// gets the user's location only when the app is in use and not background
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.startUpdatingLocation()
self.mapView.showsUserLocation = true
self.setBusStopAnnotations(summitEastBusStations)
self.canDeviceSupportAppBackgroundRefresh()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
// sends the latitude and longitude to the Apple Servers then returns the address
CLGeocoder().reverseGeocodeLocation(manager.location, completionHandler: { (placeMarks: [AnyObject]!, error: NSError!) -> Void in
if error != nil
{
println("Reverse Geocode Failed: " + error.localizedDescription)
println("The real reason is " + error.localizedFailureReason!)
return
}
if placeMarks.count > 0
{
// gets the most updated location
let pm = placeMarks.last as! CLPlacemark
let centre = CLLocationCoordinate2D(latitude: manager.location.coordinate.latitude, longitude: manager.location.coordinate.longitude)
// draws a circle in which the map will zoom to
let region = MKCoordinateRegion(center: centre, span: MKCoordinateSpan(latitudeDelta: self.mapZoomInFactor, longitudeDelta: self.mapZoomInFactor))
self.mapView.setRegion(region, animated: true)
self.displayLocationInfo(pm)
self.geoFencing()
}
})
}
func displayLocationInfo(placemark: CLPlacemark)
{
println("Current Location:")
println(placemark.name)
}
func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
println("Location Manager Failed: " + error.localizedDescription)
}
func locationManager(manager: CLLocationManager!, didStartMonitoringForRegion region: CLRegion!) {
println("The monitored regions are: (locationManager.monitoredRegions)")
}
func locationManager(manager: CLLocationManager!, monitoringDidFailForRegion region: CLRegion!, withError error: NSError!) {
println("Failed to monitor the stated region")
}
func locationManager(manager: CLLocationManager!, didEnterRegion region: CLRegion!) {
println("The bus has entered the region")
createAlert("Region Entry", alertMessage: "You have entered the specified region", alertCancelTitle: "OK")
}
func locationManager(manager: CLLocationManager!, didExitRegion region: CLRegion!) {
println("The bus has left the region")
createAlert("Region Exit", alertMessage: "You have exited the specified region", alertCancelTitle: "OK")
}
//TODO:Implement GeoFencing in order to know when the bus is at a station or not.
func geoFencing()
{
locationManager.requestAlwaysAuthorization()
let rismanPlaza = CLLocationCoordinate2D(latitude: 41.1469492, longitude: -81.344068)
var currentBusStop = CLLocation(latitude: rismanPlaza.latitude, longitude: rismanPlaza.longitude)
addRadiusCircle(currentBusStop)
let busStopRegion = CLCircularRegion(center: CLLocationCoordinate2D(latitude: rismanPlaza.latitude, longitude: rismanPlaza.longitude), radius: radius, identifier: busStopNames[1])
if radius > self.locationManager.maximumRegionMonitoringDistance
{
radius = self.locationManager.maximumRegionMonitoringDistance
}
if CLLocationManager.isMonitoringAvailableForClass(CLCircularRegion)
{
locationManager.startMonitoringForRegion(busStopRegion)
}
else
{
//TODO: Create an alert telling the user that region tracking for this area is not available
println("Monitoring is not available for this region")
}
}
// creates the radius around the specified location
func addRadiusCircle(location: CLLocation)
{
self.mapView.delegate = self
var circle = MKCircle(centerCoordinate: location.coordinate, radius: radius)
self.mapView.addOverlay(circle)
}
// performs the actual circle colouring
func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer!
{
if overlay is MKCircle
{
var circle = MKCircleRenderer(overlay: overlay)
circle.strokeColor = UIColor.redColor()
circle.fillColor = UIColor(red: 255, green: 0, blue: 0, alpha: 0.1)
circle.lineWidth = 1
return circle
}
else
{
return nil
}
}
// removes the drawn circles from the map
func removeCircleLayers()
{
var layers = mapView.overlays
mapView.removeOverlays(layers)
}
func canDeviceSupportAppBackgroundRefresh()
{
if UIApplication.sharedApplication().backgroundRefreshStatus == UIBackgroundRefreshStatus.Available
{
createAlert("Background Refresh Status", alertMessage: "Background Updates are enable for the App", alertCancelTitle: "OK")
}
else if UIApplication.sharedApplication().backgroundRefreshStatus == UIBackgroundRefreshStatus.Denied
{
createAlert("Background Refresh Status", alertMessage: "Background Updates are disabled by the user for the App", alertCancelTitle: "OK")
}
else if UIApplication.sharedApplication().backgroundRefreshStatus == UIBackgroundRefreshStatus.Restricted
{
createAlert("Background Refresh Status", alertMessage: "Background Updates are restricted and the user can't do anything App", alertCancelTitle: "OK")
}
}
func createAlert(alertTitle: String, alertMessage: String, alertCancelTitle: String)
{
let alert = UIAlertView(title: alertTitle, message: alertMessage, delegate: self, cancelButtonTitle: alertCancelTitle)
alert.show()
}
}
我最终使用了CLRegion.containsCoordinate(location.coordinate)
方法。它的工作原理基本相同。
一旦对象进入我设置的区域,它返回true,从这里我可以知道它何时进入和退出该区域
如果用户设备处于当前位置(纬度和经度),didEnterRegion:和didExitRegion:委托将不会触发。使用didDetermineState:方法来查找用户/设备是否处于被监控的当前区域。如果是,didDetermineState:将被触发。一旦用户离开区域didExitRegion:将被触发