Swift:用户位置附近的Geofencing / geolocations

问题:

我试图让它始终使用用户的位置,并不断检查它是否在我设置的CLLocationCoordinate2D点的5英里内。 如果是这样,则在应用程序打开时发送警报,或者在应用程序closures时发送通知。

有用的信息:

在我的项目中,我有4个快速文件:

Locations.swift包含CLLocationCoordinate2D点。

Utilities.swift包含一个简单的警报。

UserLocation.swift检索并更新用户的位置

GeoLocationViewController.swift监视位置

注意:

一些代码可能不在正确的位置或相关,我在看另一个项目,试图从它提取相关的代码来使用我的项目。 请告诉我,如果你发现一个错误。

码:

Locations.swift:

 import UIKit import MapKit class Locations: UIViewController { override func viewDidLoad() { super.viewDidLoad() var radius: CLLocationDistance = 5 let arroyo = CLLocationCoordinate2D (latitude: 33.781327997137595, longitude: -116.46394436519012) var arroyoCoord: CLLocationCoordinate2D = arroyo let buddyrogers = CLLocationCoordinate2D (latitude: 33.78051204742721, longitude: -116.46362250010833) var buddyCoord: CLLocationCoordinate2D = buddyrogers let chopsticks = CLLocationCoordinate2D (latitude: 33.815995425565184, longitude: -116.44107442645873) let colorfulfountain = CLLocationCoordinate2D (latitude: 33.80443304398751, longitude: -116.45723923544313) let diamond = CLLocationCoordinate2D (latitude: 33.80216859530781, longitude: -116.45711048941041) let dinahshore = CLLocationCoordinate2D (latitude: 33.806554795852996, longitude: -116.47734507421876) let fountoflife = CLLocationCoordinate2D (latitude: 33.78075282028137, longitude: -116.46407847564086) let fountains = CLLocationCoordinate2D (latitude: 33.780141969313235, longitude: -116.46346156756744) let historicphoto = CLLocationCoordinate2D (latitude: 33.78130570353292, longitude: -116.46389072100982) let holistic = CLLocationCoordinate2D (latitude: 33.781338029257775, longitude: -116.46408249895438) let hollywoodheroes = CLLocationCoordinate2D (latitude: 33.78095792254918, longitude: -116.45820483068849) let indiangathering = CLLocationCoordinate2D (latitude: 33.78136366689296, longitude: -116.46371905963287) let indianwomen = CLLocationCoordinate2D (latitude: 33.78622660767695, longitude: -116.45820483068849) let cathedrals = CLLocationCoordinate2D (latitude: 33.844502990031124, longitude: -116.45834321534426) let firehouse = CLLocationCoordinate2D (latitude: 33.78103817982461, longitude: -116.46700744788512) let perfectunion = CLLocationCoordinate2D (latitude: 33.778193459376865, longitude: -116.45877843062743) let lizards = CLLocationCoordinate2D (latitude: 33.78104263855992, longitude: -116.46340792338714) let cactus = CLLocationCoordinate2D (latitude: 33.782598723009976, longitude: -116.46699671904906) let swisscheese = CLLocationCoordinate2D (latitude: 33.78121541437478, longitude: -116.46472086469993) let newbeginning = CLLocationCoordinate2D (latitude: 33.78049421237406, longitude: -116.46463101069793) let thunderbolt = CLLocationCoordinate2D (latitude: 33.80140187863324, longitude: -116.46646603445436) let tictoc = CLLocationCoordinate2D (latitude: 33.80156235478469, longitude: -116.45524367193605) let wheeloftime = CLLocationCoordinate2D (latitude: 33.815987530910135, longitude: -116.45892863433227) let artevita = CLLocationCoordinate2D (latitude: 33.7826633, longitude: -116.46041969999999) let coachellaart = CLLocationCoordinate2D (latitude: 33.78012700000001, longitude: -116.46571840000001) let colinfisher = CLLocationCoordinate2D (latitude: 33.7819228, longitude: -116.46002010000001) let garycreative = CLLocationCoordinate2D (latitude: 33.782660, longitude: -116.462141) let lesliejean = CLLocationCoordinate2D (latitude: 33.78404799999999, longitude: -116.4635222) let rebeccafine = CLLocationCoordinate2D (latitude: 33.782487, longitude: -116.460564) let agnes = CLLocationCoordinate2D (latitude: 33.77571242620008, longitude: -116.46372063254091) let willardprice = CLLocationCoordinate2D (latitude: 33.77489419346815, longitude: -116.46667910908434) let adobe = CLLocationCoordinate2D (latitude: 33.77479870632753, longitude: -116.46673050629039) let valsamuelson = CLLocationCoordinate2D (latitude: 33.76802162366799, longitude: -116.46920998147584) let gallito = CLLocationCoordinate2D (latitude: 33.7794358, longitude: -116.4612692) let townsquare = CLLocationCoordinate2D (latitude: 33.7810365, longitude: -116.46464559999998) let ocotillo = CLLocationCoordinate2D (latitude: 33.805963, longitude: -116.46349980000002) let century = CLLocationCoordinate2D (latitude: 33.8269913, longitude: -116.4424588) let denniskeat = CLLocationCoordinate2D (latitude: 33.8304982, longitude: -116.45744730000001) let memorial = CLLocationCoordinate2D (latitude: 33.78318512716751, longitude: -116.46681405767208) let patriot = CLLocationCoordinate2D (latitude: 33.8019902897174, longitude: -116.44000872473146) let panorama = CLLocationCoordinate2D (latitude: 33.83861734636407, longitude: -116.46799619895023) let secondst = CLLocationCoordinate2D (latitude: 33.78069442561766, longitude: -116.45910418200071) let dogpark = CLLocationCoordinate2D (latitude: 33.7804269, longitude: -116.46041309999998) } } 

Utilities.swift:

 import UIKit import MapKit func showSimpleAlertWithTitle(title: String!, message: String, viewController: UIViewController) { let alert = UIAlertController(title: title, message: message, preferredStyle: .Alert) let action = UIAlertAction(title: "OK", style: .Cancel, handler: nil) alert.addAction(action) viewController.presentViewController(alert, animated: true, completion: nil) } 

UserLocation.swift:

 import UIKit import CoreLocation class UserLocation: UIViewController, CLLocationManagerDelegate { var locationManager = CLLocationManager() override func viewDidLoad() { super.viewDidLoad() if (CLLocationManager.locationServicesEnabled()) { locationManager = CLLocationManager() locationManager.delegate = self locationManager.desiredAccuracy = kCLLocationAccuracyBest locationManager.requestAlwaysAuthorization() locationManager.startUpdatingLocation() } locationManager.delegate = self locationManager.requestAlwaysAuthorization() } } 

GeoLocationViewController.swift:

 import UIKit import CoreLocation class GeoLocationViewController: UIViewController, CLLocationManagerDelegate { let locationManager = CLLocationManager() override func viewDidLoad() { super.viewDidLoad() locationManager.delegate = self locationManager.requestAlwaysAuthorization() // Do any additional setup after loading the view. } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } func regionWithGeotification(geotification: Locations) -> CLCircularRegion { // 1 let region = CLCircularRegion(center: geotification.coordinate, radius: geotification.radius, identifier: geotification.identifier) // 2 region.notifyOnEntry = (geotification.eventType == .OnEntry) region.notifyOnExit = !region.notifyOnEntry return region } func startMonitoringGeotification(geotification: Locations) { // 1 if !CLLocationManager.isMonitoringAvailableForClass(CLCircularRegion) { showSimpleAlertWithTitle("Error", message: "Geofencing is not supported on this device!", viewController: self) return } // 2 if CLLocationManager.authorizationStatus() != .AuthorizedAlways { showSimpleAlertWithTitle("Warning", message: "Your geotification is saved but will only be activated once you grant permission to access the device location.", viewController: self) } // 3 let region = regionWithGeotification(geotification) // 4 locationManager.startMonitoringForRegion(region) } func stopMonitoringGeotification(geotification: Locations) { for region in locationManager.monitoredRegions { if let circularRegion = region as? CLCircularRegion { if circularRegion.identifier == geotification.identifier { locationManager.stopMonitoringForRegion(circularRegion) } } } } func locationManager(manager: CLLocationManager, monitoringDidFailForRegion region: CLRegion?, withError error: NSError) { print("Monitoring failed for region with identifier: \(region!.identifier)") } func locationManager(manager: CLLocationManager, didFailWithError error: NSError) { print("Location Manager failed with the following error: \(error)") } } 

首先,将startMonitoringGeotification()regionWithGeotification()stopMonitoringGeotification()Geotification像Ray Wenderlich教程那样进行Geotification。 确保你已经从他的入门代码添加文件Geotification.swift到你的项目。

另外,确保您的Main.storyboard启动您的ViewController 。 没有这一步,你的代码将不会运行。

1)在Locations更简单地重新定义Locations类:

 import UIKit import MapKit class Locations { static let locations:[String:CLLocationCoordinate2D] = [ "buddyrogers" : CLLocationCoordinate2D(latitude: 33.815995425565184, longitude: -116.44107442645873), "diamond" : CLLocationCoordinate2D(latitude: 33.802168595307814, longitude: -116.45711048941041), . . // add your locations . ] } } 

就像@饥饿的雪人提出的那样

2)你可以在你的GeotificationViewController类中定义showSimpleAlertWithTitle() 。 尝试在你的ViewDidLoad()调用它来testing它。 您现在可以删除Utilities.swift

3)我认为你可以忽略/删除UserLocation.swift ,这似乎是不必要的

4)把这个代码放在GeotificationViewControllerViewDidLoad

 let radius = CLLocationDistance(8046.72) // 5 miles in meters for location in Locations.locations { let g = Geotification(coordinate: location.1, radius: radius, identifier: location.0, note: "test", eventType: EventType.OnEntry) startMonitoringGeotification(g) } 

5)我希望这有助于并简化您的代码。 派对上,如果你有任何问题,在这里回复。

看起来你正在使用Ray Wenderlich教程。 这是一个很好的,我发现它也非常有用。

首先,CLLocationDistance的单位是米,所以你所指定的代码的半径为5米,这不会像你所希望的那样有用; 8046.72的值接近5英里。

关于具体的错误,Locations是你填充所有CLLocationCoordinate2D值的类,它当然没有任何叫坐标的成员。 如果你使用的是教程,我想你需要将这些坐标加载到Geotification类的实例中。

这是一些未经testing的代码:

  // Load the various coords into an array: var locations:[(note:String, coords:CLLocationCoordinate2D)] = [] locations +=[(note: "arroyo", CLLocationCoordinate2D( latitude: 33.781327997137595, longitude: -116.46394436519012)] locations +=[(note: "buddyrogers", CLLocationCoordinate2D( latitude: 33.78051204742721, longitude: -116.46362250010833)] // ... let radius = 8000 // ~5 miles rounded to nearest km // Load the locations into geotifications: for location in locations { let geotification = Geotification(coordinate: location.cords, radius: radius, identifier: NSUUID().UUIDString, note: location.note, eventType: EventType.OnEnter) startMonitoringGeotification(geotification) } 

现在请记住,每个应用程序有20个受监视区域的硬性限制,因此,如果您有更多的区域,则需要dynamic确定最近的20个区域,然后监视这些区域。