2016-01-30 66 views
2

問題:斯威夫特:區域範圍設定/接近用戶的位置geolocations

我試圖讓這個它使用用戶的位置所有的時間和持續不斷地檢查,看是否有5英里的CLLocationCoordinate2D的內我已經設置了點。如果是這樣,它會在應用程序處於打開狀態時發出警報,或者在應用程序關閉時發出通知。

實用信息:

在我的項目我有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)") 
    } 

} 
+0

你究竟想要什麼?你卡在哪裏? –

+0

@Vishnugondlekar我希望應用程序始終使用用戶的位置,並經常檢查它們是否位於* Locations.swift *中列出的位置的5英里內。我只是不確定我是否有正確的代碼來做到這一點。我也從另一個應用程序獲取代碼。我在'let region = CLCircularRegion(center:geotification.coordinate,radius:geotification.radius,identifier:geotification.identifier)* GeoLocationViewController.swift *中有錯誤'我得到'Locations'沒有成員'座標'。以及這一行:'如果circularRegion.identifier == geotification.identifier'。 – Hunter

+0

什麼ViewController你的應用程序打開?我假設它是'GeotificationsViewController'? – mmarkman

回答

3

首先,將startMonitoringGeotification(),regionWithGeotification()stopMonitoringGeotification()改回Geotification,就像Ray Wenderlich教程一樣。確保您已將他的起始代碼中的文件Geotification.swift添加到您的項目中。

此外,請確保您的Main.storyboard啓動您的ViewController。沒有這一步,你的代碼都不會運行。

1)重新定義Locations類更簡單地在Locations.swift

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()中調用它來測試它。您現在可以刪除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)我希望這有助於並簡化了你的代碼。派對上,如果您有任何問題,請在這裏回覆。

+0

我在類中有一些錯誤。你有Dropbox嗎?如果是這樣的電子郵件是什麼?如果你可以,我可以做一個示例項目,並將它發送給你,只要這些文件,所以你可以看到的錯誤,而不是我在這裏解釋他們。一旦他們修好了,你可以把它發回來。我發現這是一個解決問題的簡單方法,就像過去一樣。 – Hunter

+0

你可以在Github上發佈你的項目,以便其他人可以從中學習嗎?如果沒有,我會製作一個Dropbox – mmarkman

+0

我沒有Github,我不知道如何使用它。如果我們現在可以使用Dropbox,那麼會很棒,然後我會找出Github。一旦我們解決了問題,我會發布鏈接到Github。 – Hunter

1

看起來你正在使用的雷Wenderlich教程。這是一個很好的例子,我發現它也很有用。

首先,CLLocationDistance的單位是米,因此您指定的代碼半徑爲5米,這不會像您所希望的那樣有用; 8046.72的值接近5英里。

關於具體的錯誤,位置是您填充所有CLLocationCoordinate2D值的類,它當然沒有任何稱爲座標的成員。如果你使用的是教程,我想你需要將這些座標加載到Geotification類的實例中。

下面是一些未經測試的代碼:

// 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個監視區域內的硬限制,所以如果你有比這更將需要動態地確定最近20然後監測這些地區。

+0

如何將座標加載到實例中? – Hunter

+0

我更新了我的答案以提供可能的解決方案。 –