虽然它在应用程序处于事件状态时工作正常,但在应用程序终止并唤醒位置更新时崩溃
我处理应用程序的代码因 didFinishLaunchingWithOptions
上的位置更新而唤醒
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate {
let locationManager = CLLocationManager()
var glat : String = ""
var glong : String = ""
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
if launchOptions?[UIApplicationLaunchOptionsLocationKey] != nil {
let locationManager = CLLocationManager() //or without this line, both crashes
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
let status = CLLocationManager.authorizationStatus()
if (status == CLAuthorizationStatus.AuthorizedAlways) {
locationManager.startMonitoringSignificantLocationChanges()
}
}
return true
}
这是 AppDelegate 上的 locationmanager 委托(delegate)
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let lat = manager.location?.coordinate.latitude,
let long = manager.location?.coordinate.longitude {
print(glat + " " + glong)
glat = String(lat)
glong = String(long)
//Line 339
updateloc(String(lat), long: String(long))
}
}
向服务器发送位置信息的函数
func updateloc(lat : String, long : String) {
let session = NSURLSession.sharedSession()
//Line 354
let request = NSMutableURLRequest(URL: NSURL(string: "URLTO/updateloc.php")!)
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.HTTPMethod = "POST"
let data = "lat=\(lat)&long=\(long)"
request.HTTPBody = data.dataUsingEncoding(NSASCIIStringEncoding)
let task = session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
if let error = error {
print(error)
}
if let response = response {
let res = response as! NSHTTPURLResponse
dispatch_async(dispatch_get_main_queue(), {
if (res.statusCode >= 200 && res.statusCode < 300)
{
do{
let resultJSON = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions())
var success = 0
if let dictJSON = resultJSON as? [String:AnyObject] {
if let successInteger = dictJSON["success"] as? Int {
success = successInteger
if success == 1
{
print("ok")
}
} else {
print("no 'success' key in the dictionary, or 'success' was not compatible with Int")
}
} else {
print("unknown JSON problem")
}
} catch _{
print("Received not-well-formatted JSON")
}
}
})
}
})
task.resume()
}
这是崩溃日志
Crashed: com.apple.main-thread
0 0x10015d998 specialized AppDelegate.updateloc(String, long : String) -> () (AppDelegate.swift:354)
1 0x10015ddf8 specialized AppDelegate.locationManager(CLLocationManager, didUpdateLocations : [CLLocation]) -> () (AppDelegate.swift:339)
2 0x100159d0c @objc AppDelegate.locationManager(CLLocationManager, didUpdateLocations : [CLLocation]) -> () (AppDelegate.swift)
3 CoreLocation 0x1893d08b8 (null) + 21836
4 CoreLocation 0x1893ccaac (null) + 5952
5 CoreLocation 0x1893c6e48 (null) + 880
6 CoreFoundation 0x18262cf84 __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 20
7 CoreFoundation 0x18262c8bc __CFRunLoopDoBlocks + 308
8 CoreFoundation 0x18262ad04 __CFRunLoopRun + 1960
9 CoreFoundation 0x182554c50 CFRunLoopRunSpecific + 384
10 GraphicsServices 0x183e3c088 GSEventRunModal + 180
11 UIKit 0x18783e088 UIApplicationMain + 204
12 0x10015a324 main (AppDelegate.swift:20)
当应用程序在 startMonitoringSignificantLocationChanges
模式下唤醒位置更新时应用程序崩溃
我真的看不出这里有什么错误。谁能帮我解决这个问题?
最佳答案
作为起点,我建议将您的位置管理器功能移动到一个单独的类,并让您的位置类订阅 UIApplicationDidFinishLaunchingNotification 通知以处理应用程序重新启动时发生的情况。
实现此目的的一种方法是让您的类成为单例,并让它通过 NSNotificationCenter 中继位置更新。
startMonitoringSignificantLocationChanges 如果在应用程序被操作系统终止时启用,它会在后台唤醒您的应用程序。
根据您想要实现的目标,您可以订阅两个不同的事件并根据应用委托(delegate)事件开始停止相关的位置服务。
作为一个广泛的(在黑暗中拍摄的)示例:
class LocationCommander {
let locationManager = CLLocationManager()
let defaultCenter = NSNotificationCenter.defaultCenter()
//- NSUserDefaults - LocationServicesControl_KEY to be set to TRUE when user has enabled location services.
let UserDefaults = NSUserDefaults.standardUserDefaults()
let LocationServicesControl_KEY = "LocationServices"
init(){
defaultCenter.addObserver(self, selector: #selector(self.appWillTerminate), name: UIApplicationWillTerminateNotification, object: nil)
defaultCenter.addObserver(self, selector: #selector(self.appIsRelaunched), name: UIApplicationDidFinishLaunchingNotification, object: nil)
}
func appIsRelaunched (notification: NSNotification) {
//- Stops Significant Location Changes services when app is relaunched
self.locationManager.stopMonitoringSignificantLocationChanges()
let ServicesEnabled = self.UserDefaults.boolForKey(self.LocationServicesControl_KEY)
//- Re-Starts Standard Location Services if they have been enabled by the user
if (ServicesEnabled) {
self.updateLocation()
}
}
func appWillTerminate (notification: NSNotification){
let ServicesEnabled = self.UserDefaults.boolForKey(self.LocationServicesControl_KEY)
//- Stops Standard Location Services if they have been enabled
if ServicesEnabled {
self.locationManager.stopUpdatingLocation()
//- Start Significant Location Changes to restart the app
self.locationManager.startMonitoringSignificantLocationChanges()
}
NSUserDefaults.standardUserDefaults().synchronize()
}
func updateLocation () {
if (CLLocationManager.authorizationStatus() == CLAuthorizationStatus.Authorized){
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.distanceFilter = kCLDistanceFilterNone
self.locationManager.startUpdatingLocation()
//- Save Location Services ENABLED to NSUserDefaults
self.UserDefaults.setBool(true, forKey: self.LocationServicesControl_KEY)
} else {
//- Unauthorized, requests permissions
}
}
}
请记住,此代码尚未经过测试,我提取了一个旧项目的片段,由于语言的更新,这些片段可能存在一些语法错误。
总体而言,我们这样做:
- 订阅相关通知
- 当应用程序即将终止时,检查我们是否正在获取位置更新,如果是,则停止标准服务并启动重大更改服务以在有新更新可用时唤醒应用程序。
- 当应用程序唤醒时,它会通知类,该类将决定我们是否继续跟踪通知更新(基于存储在 NSUserDefaults 上的值)。
您的应用可能会因为实例化一个新的位置管理器而崩溃,该管理器随后会尝试重启可能已经在运行的位置服务。
希望对您有所帮助!
关于ios - 当应用唤醒更新时 LocationManager 崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38030392/