Calling viewdidload and viewdidappear again - ios

My app is a geolocation based app. I've implemented to pop up a UIAlertview as soon as some users press "Don't allow location service" button to guide them to settings again to turn on the service.
The problem I'm facing is that when user finally turns on the button, the data are not being loaded to the tableview since my data calling functions are in viewdidload and viewdidappear. Is there a way to call those functions again?
I did something like below and it totally crashes my app:
extension ExploreViewController: CLLocationManagerDelegate {
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
switch status {
case .Denied:
// Changed status to denied
self.locationAlert = UIAlertView(title: "Location Services Permission Needed", message: "Location service needs to be turned on to use Peek! Please press setting button below and turn the service on!", delegate: self, cancelButtonTitle: "Settings")
locationAlert.show()
break
case .AuthorizedWhenInUse:
self.viewDidLoad()
self.viewDidAppear(true)
break
default
break
}
When I was doing this way, it was kept calling viewdidload like million times before it crashed the app. Any advices are appreciated

Simply move your data calling functions outside of viewDidLoad and viewDidAppear:
Instead of
override func viewDidLoad() {
// do some stuff
}
write
override func viewDidLoad() {
super.viewDidLoad()
doSomeStuff()
}
func doSomeStuff() {
// do some stuff
}
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
// do your current logic
doSomeStuff()
}

Never never never never call viewDidLoad or viewDidAppear (except, in the latter case, to call super). They are messages sent by the runtime to you, to report stages in the life of the view controller.

func myCodeToRun() {
//put all the code you want to run here
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
myCodeToRun()
}
extension ExploreViewController: CLLocationManagerDelegate {
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
switch status {
case .Denied:
// Changed status to denied
self.locationAlert = UIAlertView(title: "Location Services Permission Needed", message: "Location service needs to be turned on to use Peek! Please press setting button below and turn the service on!", delegate: self, cancelButtonTitle: "Settings")
locationAlert.show()
break
case .AuthorizedWhenInUse:
myCodeToRun()
break
default
break
}

Related

ios, displaying an alert before everything else, to inform user we'll need "some" permissions

i'm developing an app. One of the firs thing i do (in AppDelegate) is to invoke OneSignal's initwithlaunchingoptions(...)
This automatically makes my app displays "App wants to send notifications", asking for permissions.
During my app lifecycle, i'll need other permissions from user (like calendar).
I'd like to display (BEFORE all the permissions) a brief AlertView explaining what i'll ask and why.
But how can i accomplish this if i can't move the OneSignal init from AppDelegate while my "explaining alert" happens only in viewDidLoad of the Main ViewController ?
Thanks.
Victor
here is an example of UIViewController that has information about applications needs location data, when user presses UIButton, it asks for permission. you can do alike for all permissions.
class LocationRequestViewController: UIViewController, CLLocationManagerDelegate {
var locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
self.locationManager.delegate = self
}
//when user authorised or denied ->push next `UIViewController`
func locationManager(_: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status == .authorizedWhenInUse || status == .denied {
let destinationVC = self.storyboard!.instantiateViewController(withIdentifier: "Notifications Request")
self.navigationController?.pushViewController(destinationVC, animated: true)
}
}
#IBAction func requestLocation(_: UIButton) {
self.locationManager.requestWhenInUseAuthorization()
}
}

How to execute a task after location permission granted ios

I'm trying to set up an on boarding where I'm asking the user for a few permissions including: Location, Notifications and Camera. I have 3 different View Controllers set up, each asking for one of the permissions and explaining why. On each of the view controllers I have a button at the bottom that says "Grant Permission".
When the user clicks the button I want the permission dialogue to pop up, and once the user clicks allow I want to transition to the next view controller.
Here is what I have right now:
class OnboardingStep2:UIViewController{
override func viewDidLoad() {
self.view.backgroundColor = StyleKit.orangeWhite()
}
#IBAction func getPermission(sender: AnyObject) {
dispatch_sync(dispatch_get_main_queue()) {
let locManager = CLLocationManager()
locManager.requestAlwaysAuthorization()
}
if (CLLocationManager.authorizationStatus() == CLAuthorizationStatus.Authorized) {
self.performSegueWithIdentifier("goToStep3", sender: self)
}
}
}
I've tried using dispatch to queue up the tasks, but when using async the permission dialogue pops up and then immediately it closes because the authorization check is run (I'm assuming). Using dispatch_sync, the dialogue is never shown.
What is the best way to do this, I want the permission dialogue to pop up first and once the user clicks allow i want to segue.
Conform to the CLLocationManagerDelegate
Then call this:
Swift 3.0
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
switch status {
case .notDetermined:
manager.requestLocation()
case .authorizedAlways, .authorizedWhenInUse:
// Do your thing here
default:
// Permission denied, do something else
}
}
Swift 2.2
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
switch status {
case .NotDetermined:
manager.requestLocation()
case .AuthorizedAlways, .AuthorizedWhenInUse:
// Do your thing here
default:
// Permission denied, do something else
}
}
Swift 5
Implement CLLocationManagerDelegate
and this function:
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
switch CLLocationManager.authorizationStatus() {
case .notDetermined:
// User has not yet made a choice
case .denied:
// User has explicitly denied authorization
case .restricted:
// This application is not authorized to use location services.
case .authorized, .authorizedAlways, .authorizedWhenInUse:
// User has granted authorization
default:
// Other
}
}

Buttons in allow access to your location disabled

my viewController looks like following
import CoreLocation
class MyViewController: UIViewController {
let locationManager = CLLocationManager()
override func viewDidAppear(animated: Bool) {
if #available(iOS 8.0, *) {
self.locationManager.requestWhenInUseAuthorization()
} else {
// Fallback on earlier versions
}
if (CLLocationManager.locationServicesEnabled()) {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
let lon = locationManager.location!.coordinate.longitude
let lat = locationManager.location!.coordinate.latitude
print("lat = \(lat) and long = \(lon)")
}
}
}
// MARK: - CLLocationManagerDelegate
extension MyViewController : CLLocationManagerDelegate {
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
self.locationManager.stopUpdatingLocation()
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
print("\(error.localizedDescription)")
}
}
When I execute my program, it prompts a message like
Allow application to access your location while you use the app?
But the Don't Allow and Allow buttons are disabled.
Can someone guide me on where I am going wrong and what I should be doing.
I can manually allow my application to access location services by going to settings. But I would like to know why the buttons are disabled and what should I do to enable it.
note: I have added NSLocationWhenInUseUsageDescription to my info.plist file.
Thanks.
Dt: 29Oct2015
EDIT:
Uninstalled the app and installed again and tried. Now I am able to access the buttons.
Also, I noticed that sometimes the screen goes unresponsive i.e., screen cannot take any input from user. I noticed it today with a textbox. I am not able to get the cursor to the text box.
Is it something to do with IOS update? is anyone else experiencing this type of weird behaviour. Is there any workaround for the same?
Any help is highly appreciated.
Thanks.

Request User's Current Location Watch OS2

I'm trying to get a fix on the user's current location tied into displaying some data on a Map. My code is as follows for my watch kit extension.
import Foundation
import CoreLocation
class InterfaceController: WKInterfaceController, CLLocationManagerDelegate {
override func awakeWithContext(context: AnyObject?) {
super.awakeWithContext(context)
// Configure interface objects here.
}
override func willActivate() {
// This method is called when watch view controller is about to be visible to user
super.willActivate()
}
override func didDeactivate() {
// This method is called when watch view controller is no longer visible
super.didDeactivate()
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
dLog("Did get a location.")
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
dLog("Did fail to retrieve a location.")
}
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
print(status)
}
#IBAction func btnRequestLocation() {
let locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
locationManager.requestLocation()
}
I've also made sure to include the CoreLocation framework under the WatchKit extension Target Linked Frameworks and Libraries. However, running this code on both the watch simulator and a real Apple watch paired with an iOS app, these delegate callbacks never get fired. I'm not sure if I'm missing a step somewhere that would be preventing me from getting the location. I've tried resetting the location and privacy and I even get the request that my app needs location permissions. I hit "Allow" but no location is ever sent to the Apple Watch extension. Any help would be appreciated.
EDIT:
I've also taken some additional steps for iOS 9.
Project -> iOS Target -> Background Modes
- Location Updates is checked
- iOS Target also includes the "Required Background Modes" key in the plist file.
Here is the property list for the iOS App.
UPDATE
Seems this might be a common problem isolated in watch OS2.
https://forums.developer.apple.com/thread/14828
You are requesting requestAlwaysAuthorization so you need to make sure you have enabled Locations background mode and also set allowsBackgroundLocationUpdates=TRUE (for iOS9).
However, I would recommend requesting requestWhenInUseAuthorization instead since you are just calling for a onetime location update via requestLocation().

iOS 8.3 problems with location

I'm developing an application that uses the user's location. Im using core location.
But in certain screens it does not catch location. The steps are exactly these:
MainViewController:
In MainViewController I request the authorization. It's worked. I allow the authorization to location.
if CLLocationManager.authorizationStatus() == .NotDetermined {
if locationManager.respondsToSelector("requestWhenInUseAuthorization") == true {
locationManager.requestWhenInUseAuthorization()
}
}
ViewController 1:
I touch in option 1, segue to ViewController 1, here i start updating location. It's worked. A catch correct the location.
override func viewDidAppear(animated: Bool) {
locationManager.delegate = self
locationManager.startUpdatingLocation()
}
override func viewDidDisappear(animated: Bool) {
locationManager.stopUpdatingLocation()
NSLog("Location has stopped updating")
}
ViewController 2:
Now I back to MainViewController, and touch to option 2, the view segue to ViewController 2. But here in action button touchHowToGo, dont start updating location, the method has called, but not worked. If i return to ViewController 1 location start normal. Only in this screen not work.
IBAction func touchHowToGo(sender: AnyObject) {
locationManager.delegate = self
locationManager.startUpdatingLocation()
}
In this three View Controllers I'm importing CoreLocation;
In ViewController 1 and ViewController 2 setted CLLocationManagerDelegate;
In .plist I added the key;
In tha app panel settings already on to location WhenInUse;
The app not crash and not didFailError only never update location
Catch location:
In all ViewControllers i used method delegate:
func locationManager(manager: CLLocationManager!, didUpdateToLocation newLocation: CLLocation!, fromLocation oldLocation: CLLocation!) {
NSLog("Location has updated with success %f - %f", newLocation.coordinate.latitude, newLocation.coordinate.longitude)
}
I have tried didUpdateLocations, but without success

Resources