【发布时间】:2016-05-29 19:13:03
【问题描述】:
我正在使用重要的位置变化监控。当我在模拟器中运行代码并检查高速公路选项时,我会定期更新位置。我获取这些更新并将它们保存在 NSUserDefaults 中,然后每 10 秒更新一次 tableview,所以我可以查看是否有任何更新。如果我在真实设备上运行该应用程序,我将获得零更新。我把手机放在口袋里,旅行了 80 多公里,去过 2 个城市。零更新。不知道我是不是搞砸了。我附上代码。代码是复制粘贴,随意测试。只需确保在情节提要中使用 TableViewController 并将单元格 ID 设置为 ID。我错过了什么?我正在 iphone 5 上进行测试。
info.plist:
编辑:在苹果文档中找到这个。我的locationManager 应该以不同的方式创建吗?
当应用因位置更新而重新启动时,启动 传递给您的选项字典 应用程序:willFinishLaunchingWithOptions:或 application:didFinishLaunchingWithOptions: 方法包含 UIApplicationLaunchOptionsLocationKey 键。那把钥匙的存在 表示新的位置数据正在等待传送到您的应用程序。 要获取该数据,您必须创建一个新的 CLLocationManager 对象 并重新启动您之前运行的定位服务 应用程序的终止。当您重新启动这些服务时,该位置 manager 将所有待处理的位置更新传递给其委托人。
编辑2:
基于此,位置应至少每 15 分钟更新一次。我的代码中的错误已确认。
如果 GPS 级别的准确性对您的应用来说并不重要并且您不需要 持续跟踪,您可以使用显着变化的位置 服务。使用重大更改位置至关重要 服务正确,因为它至少唤醒了系统和您的应用程序 每 15 分钟一次,即使没有发生位置变化,并且它 持续运行直到你停止它。
edit3:将此代码添加到 AppDelegate didFinishLaunchingWithOptions: 以查看应用程序是否被唤醒。它不会被唤醒 - 我在表视图中看不到 200 200 条目。发生了一些可疑的事情。
if let options = launchOptions {
print("options")
if (launchOptions![UIApplicationLaunchOptionsLocationKey] != nil){
locationManager.startUpdatingLocation()
self.lat.append(Double(200))
self.lon.append(Double(200))
self.times.append(NSDateFormatter.localizedStringFromDate(NSDate(), dateStyle: .NoStyle, timeStyle: .ShortStyle))
NSUserDefaults.standardUserDefaults().setObject(lat, forKey: "lat")
NSUserDefaults.standardUserDefaults().setObject(lon, forKey: "lon")
NSUserDefaults.standardUserDefaults().setObject(times, forKey: "time")
}
代码: //AppDelegate:
import UIKit
import CoreLocation
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate {
var lat:[CLLocationDegrees]!
var lon:[CLLocationDegrees]!
var times:[String]!
var distances: [String]!
var window: UIWindow?
var locationManager: CLLocationManager!
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
locationManager=CLLocationManager()
locationManager.delegate=self
locationManager.requestAlwaysAuthorization()
let isFirstLaunch = NSUserDefaults.standardUserDefaults().objectForKey("lat")
if isFirstLaunch == nil{
lat = [CLLocationDegrees]()
lon = [CLLocationDegrees]()
times = [String]()
NSUserDefaults.standardUserDefaults().setObject(lat, forKey: "lat")
NSUserDefaults.standardUserDefaults().setObject(lon, forKey: "lon")
NSUserDefaults.standardUserDefaults().setObject(times, forKey: "time")
}else{
lat = NSUserDefaults.standardUserDefaults().arrayForKey("lat") as! [CLLocationDegrees]
lon = NSUserDefaults.standardUserDefaults().arrayForKey("lon") as! [CLLocationDegrees]
times = NSUserDefaults.standardUserDefaults().objectForKey("time") as! [String]
// distances = NSUserDefaults.standardUserDefaults().objectForKey("distance") as! [String]
}
return true
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print("location updated")
self.lat.append(locations[0].coordinate.latitude)
self.lon.append(locations[0].coordinate.longitude)
self.times.append(NSDateFormatter.localizedStringFromDate(NSDate(), dateStyle: .NoStyle, timeStyle: .ShortStyle))
NSUserDefaults.standardUserDefaults().setObject(lat, forKey: "lat")
NSUserDefaults.standardUserDefaults().setObject(lon, forKey: "lon")
NSUserDefaults.standardUserDefaults().setObject(times, forKey: "time")
print("Location: \(locations[0].coordinate.latitude) \(locations[0].coordinate.longitude)")
}
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
print("did change AS")
switch status {
case .AuthorizedWhenInUse:
locationManager.startMonitoringSignificantLocationChanges()
case .AuthorizedAlways:
print("to always")
locationManager.startMonitoringSignificantLocationChanges()
if lat.count==0{
self.lat.append((locationManager.location?.coordinate.latitude)!)
self.lon.append((locationManager.location?.coordinate.longitude)!)
self.times.append(NSDateFormatter.localizedStringFromDate(NSDate(), dateStyle: .NoStyle, timeStyle: .ShortStyle))
NSUserDefaults.standardUserDefaults().setObject(lat, forKey: "lat")
NSUserDefaults.standardUserDefaults().setObject(lon, forKey: "lon")
NSUserDefaults.standardUserDefaults().setObject(times, forKey: "time")
}
// locationManager.startUpdatingLocation()
break
default:
locationManager.stopMonitoringSignificantLocationChanges()
break
}
}
}
// 视图控制器
import UIKit
class TableViewController: UITableViewController {
let appDel = UIApplication.sharedApplication().delegate as! AppDelegate
override func viewDidLoad() {
super.viewDidLoad()
NSTimer.scheduledTimerWithTimeInterval(10, target: self, selector: "updateTableView", userInfo: nil, repeats: true)
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return appDel.lon.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("ID", forIndexPath: indexPath)
cell.textLabel?.text = "\(appDel.lat[indexPath.row]) \(appDel.lon[indexPath.row]) \(appDel.times[indexPath.row])"
cell.textLabel?.font = UIFont.systemFontOfSize(9)
return cell
}
func updateTableView(){
self.tableView.reloadData()
}
}
【问题讨论】:
-
您真的看到授权请求了吗?如果没有,您的 plist 中有 NSLocationAlwaysUsageDescription 吗?
-
是的,请求弹出。是的,NSLocationAlwaysUsageDescription 字符串是在 info.plist 中设置的。
-
您是否通过双击主页按钮并在应用程序上向上滑动来杀死应用程序?如果您以这种方式杀死一个应用程序,它将不会运行后台重大更改服务。
-
是的,我正在这样做。我认为大多数用户也经常这样做。有没有更好的暂停应用程序?
-
不,这不会暂停应用程序,会完全杀死它并阻止进一步的后台交互。无需杀死应用程序,只需轻按一次主页按钮并转到另一个应用程序,而不会杀死另一个应用程序。
标签: ios core-location cllocationmanager