I would suggest to do this:
this singleton to wrap location.
Sorry, for swift3 but it have look something like this:
class LM: NSObject, CLLocationManagerDelegate {
//MARK: Public Variable
var lat = 0.0
var lon = 0.0
var CAST = "location_cast"
public static let i : LM = {
let instance = LM()
return instance
}()
//MARK: Local Variable
fileprivate var locationManager: CLLocationManager?
//MARK: Init
public override init() {
super.init()
locationManager = CLLocationManager()
locationManager?.delegate = self
}
internal func start() {
locationManager?.startUpdatingLocation()
}
internal func stop() {
locationManager?.startUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
//code
print("\(error)")
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
//code
// print("\(locations)")
if let loc = locations.last {
//simple store to retrieve it later
lat = loc.coordinate.latitude
lon = loc.coordinate.longitude
//cast here notification
NotificationCenter.default.post(name: NSNotification.Name(rawValue: CAST), object: ["lat": lat, "lon": lon])
}
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
switch status {
case .notDetermined:
manager.requestAlwaysAuthorization()
break
case .authorizedWhenInUse:
manager.startUpdatingLocation()
break
case .authorizedAlways:
manager.startUpdatingLocation()
break
case .restricted:
// restricted by e.g. parental controls. User can't enable Location Services
break
case .denied:
// user denied your app access to Location Services, but can grant access from Settings.app
break
}
}
}
to start and stop this locationmanager use this:
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
//...
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
// Override point for customization after application launch.
_ = LM.i
return true
}
func applicationWillResignActive(_ application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
LM.i.stop()
}
func applicationDidBecomeActive(_ application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
LM.i.start()
}
}
You can add inside AppDelegate
your custom timer with casting variables each 1 second
let CASTTOVIEWCONTROLLER = "CASTTOVIEWCONTROLLER"
NotificationCenter.default.post(name: NSNotification.Name(rawValue: CASTTOVIEWCONTROLLER), object: ["lat": LM.i.lat, "lon": LM.i.lon])
or even simple
let CASTTOVIEWCONTROLLER_PING = "CASTTOVIEWCONTROLLER_PING"
NotificationCenter.default.post(name: NSNotification.Name(rawValue: CASTTOVIEWCONTROLLER), object: nil)
to catch a new data from casted values use something like this:
https://stackoverflow.com/a/38615219/1979882
If you will not manage .start()
and .stop()
iOS will kick your background timer application each in several minutes if your will press 'home' button.