Hi all as titled, I am creating an app (Lets give this app name as 'TM').
TM is a GPS Location Navigatator app that will trigger an alarm when user is reaching at some point near the destination.
So it needs MapKit & CoreLocation.
TM also receives Tweets from Public Transport Operator's official twitter account about the Subway's availability.
It should send a notification to user whenever a service disruption occured.
In either case, I need to have 'Background Fetch' capability enabled right?
This was what I did:
import UIKit
import Foundation
import CoreLocation
class Planner: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//I start a Background Fetch function check when I start to load this page (One of the 4 tabs in my app).
backgroundThread(0.0, background: {
let bm = BackgroundManager()
bm.checkBackground()
})
}
override func viewDidAppear(animated: Bool) {}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
//I wanted to create a Background Thread that can consistently check for Background Refresh permission is enabled.
func backgroundThread(delay: Double = 0.0, background: (() -> Void)? = nil, completion: (() -> Void)? = nil) {
dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_USER_INITIATED.rawValue), 0)) {
if(background != nil){ background!(); }
let popTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC)))
dispatch_after(popTime, dispatch_get_main_queue()) {
if(completion != nil){ completion!(); }
}
}
}
}
With such code, I still cannot get the dialog box to show even I had disabled Background Refresh on my device.
import Foundation
import UIKit
class BackgroundManager: UIViewController {
func checkBackground(){
let status = UIApplication.sharedApplication().backgroundRefreshStatus
switch(status)
{
case UIBackgroundRefreshStatus.Denied:
//Background Refresh denied. So show a popup to request user to enable it.
let alert = UIAlertController(title: “Background Fetch is disabled”, message: “Turn on Background Fetch for best Experience”, preferredStyle: UIAlertControllerStyle.Alert)
//OK button goes to relevant settings
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler:
{
action in
/
UIApplication.sharedApplication().openURL(NSURL(string: UIApplicationOpenSettingsURLString)!)
}
))
//Cancel button close this dialog
alert.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: nil))
//Show user this popup
self.presentViewController(alert, animated: true, completion: nil)
break
case UIBackgroundRefreshStatus.Restricted:
//TM is running on Restricted mode, perhaps blocked by Parental Controls
//Show an alert to user for this fact
let alert = UIAlertController(title: "TM running on restricted mode“, message: “TM cannot enable Background Fetch for best experience”, preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Cancel, handler: nil))
//Shows a 1 button Popup to dismiss this message.
self.presentViewController(alert, animated: true, completion: nil)
break
default:
//Do nothing when the feature is enabled
break
}
}
}
However, I still get the following error messages:
Warning: Unable to create restoration in progress marker file
Warning: Attempt to present UIAlertController: 0x13debaa90 on TM.BackgroundManager: 0x13df24ce0 whose view is not in the window hierarchy!
Thus, what should I do now in order to ensure this app gets the Background Refresh permission except when Parental Controls is running?
That error message indicates you're trying to present the alert controller from a view controller that's not being displayed. Rather than calling presentViewController on "self", you will need to use a view controller that's actually visible, such as your main UIWindow's rootViewController.
Also none of the code you've shown has anything to do with background fetch. Having that permission does NOT give your app permission to run a background thread forever. That background thread you're starting will be suspended along with the rest of the app eventually. Background fetch is a hint to the OS that it should wake your app up periodically with a call to your app delegate's performFetchWithCompletionHandler whenever it feels like it.