User Inactivity, display screensaver using AppDelegate Swift 4 - ios

I need to detect user inactivity on all view controllers, by detecting all touches made. My current AppDelegate code is not detecting the touches made on UIButton and other UI controls. How do I detect all touches made, including UIButtons, UILabels and UITextfields? I have looked at many Stack Overflow articles but I cant seem to adapt it to my needs. If this is not possible how do I extend my original TimerUIApplication class to the other views to detect touches made. Thanks in advance.
AppDegegate Code:
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate{
var window: UIWindow?
static let ApplicationDidTimoutNotification = "AppTimout"
// The timeout in seconds for when to fire the idle timer.
let timeoutInSeconds: TimeInterval = 5
var idleTimer: Timer?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
application.isIdleTimerDisabled = true
let userDefaults = UserDefaults.standard
let defaultValues = ["promotionIsEnabled_preference" : "YES",
"promotionDuration_preference" : "10"]
userDefaults.register(defaults: defaultValues)
userDefaults.synchronize()
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.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
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.
print ("app started")
self.resetIdleTimer()
idleTimer = Timer.scheduledTimer(timeInterval: timeoutInSeconds, target: self, selector: #selector(AppDelegate.idleTimerExceeded), userInfo: nil, repeats: false)
}
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
print("touched")
self.resetIdleTimer()
}
// Resent the timer because there was user interaction.
func resetIdleTimer() {
if let idleTimer = idleTimer {
idleTimer.invalidate()
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
self.resetIdleTimer()
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
idleTimer = Timer.scheduledTimer(timeInterval: timeoutInSeconds, target: self, selector: #selector(AppDelegate.idleTimerExceeded), userInfo: nil, repeats: false)
}
#objc func idleTimerExceeded() {
NotificationCenter.default.post(name: Notification.Name(rawValue: TimerUIApplication.ApplicationDidTimoutNotification), object: nil)
print ("Inactive User")
let mainStoryboardIpad : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let initialViewControlleripad : UIViewController = mainStoryboardIpad.instantiateViewController(withIdentifier: "mainPromo") as UIViewController
self.window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = initialViewControlleripad
self.window?.makeKeyAndVisible()
}
}
Original Code that I used in the AppDelegate.
import UIKit
import Foundation
class TimerUIApplication: UIApplication {
static let ApplicationDidTimoutNotification = "AppTimout"
// The timeout in seconds for when to fire the idle timer.
let timeoutInSeconds: TimeInterval = 5
var idleTimer: Timer?
// Resent the timer because there was user interaction.
func resetIdleTimer() {
if let idleTimer = idleTimer {
idleTimer.invalidate()
}
idleTimer = Timer.scheduledTimer(timeInterval: timeoutInSeconds, target: self, selector: #selector(TimerUIApplication.idleTimerExceeded), userInfo: nil, repeats: false)
}
// If the timer reaches the limit as defined in timeoutInSeconds, post this notification.
#objc func idleTimerExceeded() {
NotificationCenter.default.post(name: Notification.Name(rawValue: TimerUIApplication.ApplicationDidTimoutNotification), object: nil)
print ("out")
}
override func sendEvent(_ event: UIEvent) {
super.sendEvent(event)
if idleTimer != nil {
self.resetIdleTimer()
}
if let touches = event.allTouches {
for touch in touches {
if touch.phase == UITouchPhase.began {
self.resetIdleTimer()
}
}
}
}
}

Swift 4 - Create a CustomWindow in your AppDelegate.swift which goes over your Storyboard Views, that registers touches, but does not cancel them.
Code:
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate{
var topWindow: CustomWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
topWindow = CustomWindow(frame: UIScreen.main.bounds)
topWindow?.rootViewController = UIViewController()
topWindow?.windowLevel = UIWindowLevelNormal + 1
topWindow?.isHidden = false
}
Create a CustomWindow.swift class that recieves your actions and handles them. Code:
import UIKit
class CustomWindow: UIWindow{
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
// What you want to do in here.
return false
}

Related

morpher app soundboard does not contain a valid Info.plist so it cannot be installed on Jared iPhone CFBundleExecutable isn't specified. What do I do?

This happens when I try to run the app on my phone. here is the error
“morpher app soundboard” does not contain a valid Info.plist, so it cannot be installed on Jared's iPhone
(“CFBundleExecutable” is not specified)
How do I fix this error?
here is the code
from the viewController.swift file
import UIKit
import AVFoundation
class ViewController: UIViewController {
class ViewController: UIViewController, UIGestureRecognizerDelegate{
let soundFilenames = ["5","8","7","4","6","1","3","2"]
var audioPlayers = [AVAudioPlayer]()
var lastAudioPlayer = 0
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// Set up audio players
for sound in soundFilenames {
do {
let url = URL(fileURLWithPath: Bundle.main.path(forResource: sound, ofType: "wav")!)
let audioPlayer = try AVAudioPlayer (contentsOf:url)
audioPlayers.append(audioPlayer)
}
catch {
audioPlayers.append(AVAudioPlayer())
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func buttonTapped(_ sender: UIButton) {
// Get the audioPlayer that corresponds to the button that they tapped
let lastPlayer = audioPlayers[lastAudioPlayer]
lastPlayer.stop();
lastAudioPlayer = sender.tag;
lastPlayer.currentTime = 0;
let audioPlayer = audioPlayers[sender.tag]
audioPlayer.currentTime=0;
audioPlayer.play();
}
#IBAction func button(_ sender: UIButton) {
// Get the audioPlayer that corresponds to the button that they tapped
let lastPlayer = audioPlayers[lastAudioPlayer]
lastPlayer.stop();
lastAudioPlayer = sender.tag;
lastPlayer.currentTime = 0;
let audioPlayer = audioPlayers[sender.tag]
audioPlayer.currentTime=0;
audioPlayer.play()
}
}
}
and here is the code from the appDelegate.swift file
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate { //Error happens on this line... Thread 1: signal SIGABRT
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
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.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
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.
}
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
}
and also if you were wondering...
here is the plist file

User Notifications Swift 3

I want to send simple User Notifications when a Button is pressed. I used a tutorial from the internet, bit it still doesn't work.
The error is "Thread 1: Signal SIGABRT" in the AppDelegate
Here ist the Code:
import UIKit
import UserNotifications
class Map: UIViewController, UNUserNotificationCenterDelegate {
override func viewDidLoad() {
super.viewDidLoad()
//Senden von Mitteilungen?
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.alert, .sound]) { (granted, error) in
}
// Do any additional setup after loading the view.
}
#IBAction func Notification(_ sender: Any) {
//Set the content of the notification
let content = UNMutableNotificationContent()
content.title = "Achtung!"
content.subtitle = "Verbindung zum Beacon wurde getrennt"
content.body = "---"
//Set the trigger of the notification -- here a timer.
let trigger = UNTimeIntervalNotificationTrigger(
timeInterval: 10.0,
repeats: false)
//Set the request for the notification from the above
let request = UNNotificationRequest(
identifier: "10.second.message",
content: content,
trigger: trigger
)
//Add the notification to the currnet notification center
UNUserNotificationCenter.current().add(
request, withCompletionHandler: nil)
}
}
This is the App Delegate:
import UIKit
import Firebase
import CoreLocation
import UserNotifications
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
FIRApp.configure()
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.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
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.
}
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
}
//EXTENSIONS
// Die Tastatur wird geschlossen, sobald der User außerhalb von ihr klickt
extension UIViewController {
func hideKeyboardWhenTappedAround() {
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(UIViewController.dismissKeyboard))
view.addGestureRecognizer(tap)
}
func dismissKeyboard() {
view.endEditing(true)
}
}
I hope someone knows my mistake :)
Rename your #IBAction method to something else. You have a namespace conflict.
Ensure the #IBAction is actually linked to a button and fired (add a comment or breakpoint to the method).
Edit: Move your FIRApp.configure() out of applicationDidFinishLaunchingWithOptions. This has been known to cause crashes.
...
override init() {
FIRApp.configure()
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
return true
}
...
Tip: start method names with a lowercase letter. Classes with uppercase letters. This way you can easily identify these later.

iPhone freeze when using QuickActionItems

I have added 3D Touch on my app icon to show Quick Action menu. I think I should have it all set up correctly.
The problem is that when I am choosing one of the items in the Quick Action menu, the iPhone freezes for a few seconds before it opens up the application.
This is my AppDelegate.swift:
import UIKit
import Parse
#available(iOS 9.0, *)
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
Parse.setApplicationId("xx",
clientKey: "xx")
let currentInstallation: PFInstallation = PFInstallation.currentInstallation()
currentInstallation.badge = 0
currentInstallation.saveEventually()
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.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
func applicationDidEnterBackground(application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(application: UIApplication) {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
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.
}
func applicationWillTerminate(application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
func application(application: UIApplication, performActionForShortcutItem shortcutItem: UIApplicationShortcutItem, completionHandler: (Bool) -> Void) {
let rootNavigationViewController = window!.rootViewController as? UINavigationController
let rootViewController = rootNavigationViewController?.viewControllers.first as UIViewController?
rootNavigationViewController?.popToRootViewControllerAnimated(false)
if shortcutItem.type == "JEGHARALDRI" {
rootViewController?.performSegueWithIdentifier("JEGHARALDRISEGUE", sender: nil)
}
if shortcutItem.type == "PLING" {
rootViewController?.performSegueWithIdentifier("PLINGSEGUE", sender: nil)
}
if shortcutItem.type == "FLASKETUTENPEKERPÅ" {
rootViewController?.performSegueWithIdentifier("FLASKETUTENPEKERPÅSEGUE", sender: nil)
}
if shortcutItem.type == "KORTETTALER" {
rootViewController?.performSegueWithIdentifier("KORTETTALERSEGUE", sender: nil)
}
}
}
I think your app delegate should more looks like something like this
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
//MARK: - Properties
var window: UIWindow?
lazy var quickActionManager: QuickActionsManager = {
return QuickActionsManager()
}()
//MARK: - AppDelegate Methods
func application(application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
{
return self.setupQuickActions(launchOptions)
}
func application(application: UIApplication, performActionForShortcutItem
shortcutItem: UIApplicationShortcutItem, completionHandler: (Bool) -> Void)
{
completionHandler(self.quickActionManager.handleShortcut(shortcutItem))
}
//MARK: - Private Methods
private func setupQuickActions(launchOptions: [NSObject: AnyObject]?) -> Bool
{
guard let shortcutItem = launchOptions?[UIApplicationLaunchOptionsShortcutItemKey]
as? UIApplicationShortcutItem else { return false }
return self.quickActionManager.handleShortcut(shortcutItem)
}
}
And so then you get all the logic to handle a quick action in your quick action manager, which would looks something like this
//MARK: - Public Methods
func handleShortcut(shortcut: UIApplicationShortcutItem?) -> Bool
{
guard let shortcut = shortcut else { return false }
// Get the key of the shortcutItem
let key = self.shortKeyForType(shortcut.type)
// Check if that key is the key of a knowed viewController
guard let viewControllerKey = ViewControllerKeys(rawValue: key) else { return false }
// Try to show This View Controller
return self.showViewController(viewControllerKey)
}
Assuming you got an enum of viewController to display matching each quick actions.
I hope this answer your question, let me know if you got some more.

How to change the swift file that will show on load programmatically?

I've got three different .swift files, GameScene.swift, GameOverScene.swift, and StartScene.swift. When I open my app, GameScene shows up. How can I change it so that StartScene.swift is the first file that is displayed? I have been working all in code so a way to do this without the storyboard would be nice. Thanks for the help!
EDIT:
I feel like I've got to change something in GameViewController.swift so heres the code for that.
extension SKNode {
class func unarchiveFromFile(file : String) -> SKNode? {
if let path = NSBundle.mainBundle().pathForResource(file, ofType: "sks") {
var sceneData = NSData(contentsOfFile: path, options: .DataReadingMappedIfSafe, error: nil)!
var archiver = NSKeyedUnarchiver(forReadingWithData: sceneData)
archiver.setClass(self.classForKeyedUnarchiver(), forClassName: "SKScene")
let scene = archiver.decodeObjectForKey(NSKeyedArchiveRootObjectKey) as! GameScene
archiver.finishDecoding()
return scene
} else {
return nil
}
}
}
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("pauseTimers:"), name:UIApplicationWillResignActiveNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("startTimers:"), name:UIApplicationDidBecomeActiveNotification, object: nil)
if let scene = GameScene.unarchiveFromFile("GameScene") as? GameScene {
// Configure the view.
let skView = self.view as! SKView
skView.showsFPS = true
skView.showsNodeCount = true
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = true
/* Set the scale mode to scale to fit the window */
scene.size = skView.bounds.size
scene.scaleMode = .AspectFill
skView.presentScene(scene)
}
}
func pauseTimers(notification : NSNotification) {
println("Observer method called")
timer.invalidate()
scoretimer.invalidate()
supertimer.invalidate()
}
func startTimers(notification : NSNotification) {
println("Observer method called")
timerRecreate = true
timerz = false
}
override func shouldAutorotate() -> Bool {
return false
}
override func supportedInterfaceOrientations() -> Int {
if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
return Int(UIInterfaceOrientationMask.AllButUpsideDown.rawValue)
} else {
return Int(UIInterfaceOrientationMask.All.rawValue)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Release any cached data, images, etc that aren't in use.
}
override func prefersStatusBarHidden() -> Bool {
return true
}
}
I tried changing everything that said gamescene to StartScene but that didn't work.
Heres the list of files:
And heres my app delegate:
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
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.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
func applicationDidEnterBackground(application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(application: UIApplication) {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
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.
}
func applicationWillTerminate(application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
}
EDIT:
I tried implementing the second method in the post below but I got three errors.
With storyboard go into your app delegate and look for this method
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject :AnyObject]?) -> Bool {
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
var storyboard = UIStoryboard(name: "Main", bundle: nil)
var initialViewController = storyboard.instantiateViewControllerWithIdentifier("ViewController") as UIViewController
self.window?.rootViewController = initialViewController
self.window?.makeKeyAndVisible()
}
If you aren't using Storyboard
window: UIWindow?
var initialViewController :StartScene?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject :AnyObject]?) -> Bool {
initialViewController = StartScene(nibName:"StartScene",bundle:nil)
let frame = UIScreen.mainScreen().bounds
window = UIWindow(frame: frame)
window!.rootViewController = initialViewController
window!.makeKeyAndVisible()
...
}

App location in background on iOS 8

I want get a user's location in app background. It works fine if I use a timer of 9 or less seconds. If I use 10 and more seconds I can't get the user's location...
My AppDelegate.swift:
import UIKit
import CoreLocation
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate {
var window: UIWindow?
var backgroundTaskIdentifier: UIBackgroundTaskIdentifier = UIBackgroundTaskInvalid
var myTimer: NSTimer?
var locationManager = CLLocationManager()
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
return true
}
func isMultitaskingSupported() -> Bool {
return UIDevice.currentDevice().multitaskingSupported
}
func timerMethod(sender: NSTimer) {
let backgroundTimerRemainig = UIApplication.sharedApplication().backgroundTimeRemaining
self.locationManager.startUpdatingLocation()
if backgroundTimerRemainig == DBL_MAX {
println("test1")
} else {
println("test")
self.locationManager.delegate = self
self.locationManager.startUpdatingLocation()
}
}
func applicationWillResignActive(application: UIApplication) {
}
func applicationDidEnterBackground(application: UIApplication){
if !isMultitaskingSupported() {
return
}
myTimer = NSTimer.scheduledTimerWithTimeInterval(60.0,
target: self,
selector: "timerMethod:",
userInfo: nil,
repeats: true)
backgroundTaskIdentifier = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler {
() -> Void in
UIApplication.sharedApplication().endBackgroundTask(self.backgroundTaskIdentifier)
}
}
func endBackgroundTask() {
let mainQueue = dispatch_get_main_queue()
dispatch_async(mainQueue) {
[weak self] in
if let timer = self!.myTimer {
timer.invalidate()
self!.myTimer = nil
UIApplication.sharedApplication().endBackgroundTask(self!.backgroundTaskIdentifier)
self!.backgroundTaskIdentifier = UIBackgroundTaskInvalid
}
}
}
func applicationWillEnterForeground(application: UIApplication) {
if backgroundTaskIdentifier != UIBackgroundTaskInvalid {
endBackgroundTask()
}
}
func applicationDidBecomeActive(application: UIApplication) {
}
func applicationWillTerminate(application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
func locationManager(manager: CLLocationManager!, didUpdateToLocation locations: [AnyObject]) {
var latValue = locationManager.location.coordinate.latitude
var lonValue = locationManager.location.coordinate.longitude
}
}
Why can't I get the user's location when I use 10 and more seconds?
Because approximately after 10 seconds after calling didEnterBackground the app gets suspended.
The app is in the background but is not executing code. The system
moves apps to this state automatically and does not notify them before
doing so. While suspended, an app remains in memory but does not
execute any code.
It's the iOS app lifecycle.
If you want to get location updates in background you have two options:
background task - but it only keeps the app running for 3 minutes maximum
Run update locations background mode.

Resources