我正在使用重要的位置更改监控。当我在模拟器中运行代码并选中Freeway选项时,我会得到定期的位置更新。我获取这些更新并将其保存在NSUserDefaults中,然后每隔10s更新一次tableview,这样我就可以查看是否有任何更新。如果我在真实设备上运行该应用程序,则会得到零更新。我把手机放在口袋里,走了80多公里,去了两个城市。零更新。不知道我是否搞砸了。我正在附上代码。该代码是复制粘贴,随时可以测试。只要确保在情节提要中使用TableViewController并将单元格ID设置为ID即可。我想念什么?我正在iPhone 5上进行测试。
info.plist:
编辑:在苹果文档中找到了这个。我的locationManager
创作方式是否应与众不同?
当由于位置更新而重新启动应用程序时,启动选项字典传递给您的应用程序:willFinishLaunchingWithOptions:或application:didFinishLaunchingWithOptions:方法包含UIApplicationLaunchOptionsLocationKey键。该键的存在表明新的位置数据正在等待传递到您的应用程序。要获取该数据,必须创建一个新的CLLocationManager对象并重新启动在终止应用程序之前运行的位置服务。重新启动这些服务时,位置管理器会将所有未决的位置更新传递给其委托。
编辑2:
基于此,应该至少每15分钟更新一次位置。我的代码中的错误已确认。
如果GPS级别的精度对您的应用不是很关键,并且您不需要连续跟踪,则可以使用重大变化的位置服务。正确使用重要更改位置服务至关重要,因为即使没有发生位置更改,它也至少每15分钟唤醒一次系统和您的应用,并且该服务会连续运行直到您停止它为止。
edit3:将此代码添加到AppDelegate中,didFinishLaunchingWithOptions:
以查看应用是否被唤醒。它不会被唤醒-我在表视图中看不到200200条目。可疑的事情正在发生。
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()
}
}
该代码有几个问题:
以下是相关文件:
第一个文档说,iOS启动应用程序时必须完全配置位置管理器对象,以便可以将位置事件传递给应用程序。
重新启动后,您仍然必须配置位置管理器对象并调用此方法[startMonitoringSignificantLocationChanges]以继续接收位置事件。
我通常这样做是为了确保位置管理器完全启动,而不管它是从图标启动还是通过iOS启动(对不起,我使用ObjectiveC)。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
NSLog(@"app launching");
bgTask = UIBackgroundTaskInvalid;
locationMgr = [[CLLocationManager alloc] init];
[locationMgr setDelegate:self];
if([locationMgr respondsToSelector:@selector(setAllowsBackgroundLocationUpdates:)])
[locationMgr setAllowsBackgroundLocationUpdates:YES];
CLAuthorizationStatus authorizationStatus= [CLLocationManager authorizationStatus];
if([launchOptions valueForKey:UIApplicationLaunchOptionsLocationKey] != nil) {
NSLog(@"relaunching because of significant location change - restarting SLC");
[locationMgr startMonitoringSignificantLocationChanges];
}
else
{
if (authorizationStatus == kCLAuthorizationStatusAuthorizedAlways) {
NSLog(@"launching with authorization to always use location - starting SLC");
[locationMgr startMonitoringSignificantLocationChanges];
}
else
{
NSLog(@"launching with no authorization to always use location - requesting authorization");
if([locationMgr respondsToSelector:@selector(requestAlwaysAuthorization)])
[locationMgr requestAlwaysAuthorization];
}
}
return YES;
}
请注意对setAllowsBackgroundLocationUpdates的调用。这是iOS9中的新功能,如果您想在后台接收位置更新,则必须在每次启动应用程序时进行。(这就像“我不是在开玩笑,我知道我在后台模式下要它们,但我确实想要它们”)。
希望在挂起时接收位置更新的应用程序必须在其应用程序的Info.plist文件中包含UIBackgroundModes键(具有位置值),并将此属性的值设置为YES。
最后,您不能依靠didChangeAuthorizationStatus被调用。如果您具有授权kCLAuthorizationStatusAuthorizedAlways,则调用[locationMgr requestAlwaysAuthorization]不会导致授权状态发生更改,因此不会调用ChangeAuthorizationStatus。
如果在调用requestWhenInUseAuthorization或requestAlwaysAuthorization方法时已经知道授权状态,则位置管理器不会向此方法报告当前授权状态。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句