Location always nil on WatchOS2 - xcode

I'm trying to retrieve de Lat Long of my current position on my WatchOS2 app.
The app is authenticated and the iPhone app works fine.
info.plist: NSLocationWhenInUseUsageDescription is set.
I use the following code in the willActivate()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
if (CLLocationManager.authorizationStatus() != CLAuthorizationStatus.AuthorizedWhenInUse)
{
locationManager.requestWhenInUseAuthorization()
print("Logon: Location not authorized1")
}
}
locationManager.requestLocation()
In the locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) i run this code:
if locationManager.location != nil
{
self.userLat = String(self.locationManager.location!.coordinate.latitude)
self.userLong = String(self.locationManager.location!.coordinate.longitude)
print("Lat\(userLat) Long \(userLong)")
}
else
{
print("An error occurred") <- It always prints this error
}
}
locationManager(manager: CLLocationManager, didFailWithError error: NSError)
is not being called

I've found a library which solved my problem. I don't know what exactly happend but it works now.
I used the OneShotLocationManger by icanzilb
I've you want to use this in your WatchOS2 app, you'll have to change startUpdatingLocation() to requestLocation(), because WatchOS doesn't allow continues updates.
like so:
//location authorization status changed
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
switch status {
case .AuthorizedWhenInUse:
self.locationManager!.requestLocation()
case .Denied:
_didComplete(nil, error: NSError(domain: self.classForCoder.description(),
code: OneShotLocationManagerErrors.AuthorizationDenied.rawValue,
userInfo: nil))
default:
break
}
}
Give Credit Where Credit Is Due -

Related

Unable to scan for iBeacons on macOS

I am attempting a very simple AppKit app on MacOS which displays nearby iBeacons.
I don't appear to ever have region scanning available on my system though. Am I doing something wrong?
FYI: My system is a MacBook Pro (16-inch, 2019) running Catalina (10.15.7)
The target has 'Bluetooth' and 'App Location' enabled in the 'App Sandbox' capabilities section and 'Location' enabled under 'Hardened Runtime'.
The code below always gives the following:
LM Auth Status is now: Authorised Always
Beacon monitoring is not available
starting scanning
region monitoring failed: Error Domain=kCLErrorDomain Code=5 "(null)"
// ViewController.swift
// Beacons
import Cocoa
import CoreLocation
class ViewController: NSViewController, CLLocationManagerDelegate {
var locationManager: CLLocationManager!
override func viewDidLoad() {
super.viewDidLoad()
locationManager = CLLocationManager()
locationManager.requestAlwaysAuthorization()
locationManager.delegate = self
}
#IBAction func buttonTapped(_ sender: NSButton) {
self.startScanning()
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
func startScanning() {
print("starting scanning")
//UUID Obscured for forum post...
guard let uuid = UUID(uuidString: "xxxxxxxx-E4A1-4720-9034-xxxxxxxxxxxx") else {
print("Couldn't make UUID")
return
}
let beaconID = "com.monkeyfood.myBeaconRegion"
let beaconRegion = CLBeaconRegion(uuid: uuid, identifier: beaconID)
// let beaconRegion = CLBeaconRegion(uuid: UUID(), identifier: beaconID)
self.locationManager.startMonitoring(for: beaconRegion)
}
//. CLLocationManagerDelegate Methods
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
var newStatus = ""
switch status {
case .notDetermined:
newStatus = "Not determined"
case .restricted:
newStatus = "Restricted"
case .denied:
newStatus = "Denied"
case .authorizedAlways:
newStatus = "Authorised Always"
case .authorized:
newStatus = "Authorised"
default:
newStatus = "What?"
}
print("LM Auth Status is now: \(newStatus)")
// Check for iBeacon monitoring status
let regionMonitoringIsAvailable = CLLocationManager.isMonitoringAvailable(for: CLBeaconRegion.self)
let not = regionMonitoringIsAvailable ? "" : "not "
print("Beacon monitoring is \(not)available")
}
func locationManager(_ manager: CLLocationManager, didRangeBeacons beacons: [CLBeacon], in region: CLBeaconRegion) {
if beacons.count > 0 {
// updateDistance(beacons[0].proximity)
print("\(beacons.count) beacons found.")
print("\(beacons[0].proximity) dist.")
} else {
// updateDistance(.unknown)
}
}
func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
print("region entered... \(region)")
}
func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) {
print("region exited... \(region)")
}
func locationManager(_ manager: CLLocationManager, didDetermineState state: CLRegionState, for region: CLRegion) {
print("determined region state")
}
func locationManager(_ manager: CLLocationManager, monitoringDidFailFor region: CLRegion?, withError error: Error) {
print("region monitoring failed: \(error)")
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("LM failed \(error)")
}
}
I do not believe that Beacon monitoring with CoreLocation works on any MacOS version.
I looked at the class docs to confirm this and was surprised to see that the CLBeacon class docs do say it is supported on MacOS 10.15+. I don't know if this is a mistake, or simply an indication that the SDKs for MacOS 10.15+ support these classes even though you can't really use them.
The last time I worked with these APIs on MacOS was in 2018 when MacOS 2.14 was new. Back then, I had to use CoreBluetooth to do raw BLE advertisement scanning on MacOS and parse out beacons myself. I doubt anything has changed since then. I do not remember hearing anything about beacon support being added to MacOS, and just doing a quick search now, I can find no discussion of this starting with WWDC 2019. I doubt I missed such a change, but I would be thrilled to learn that I did!

CLLocationManager: didChangeAuthorizationStatus not called in iOS 13

I have an app that has been working fine for several years, but location services are not working properly for iOS 13 on newer iPhones. Works fine on 7 and below. When the CLLocationManager is initialized the CLLocationManager: didChangeAuthorizationStatus method is not called.
Here is the code:
var firstMapLoad = true
let locationManager = CLLocationManager()
locationManager.pausesLocationUpdatesAutomatically = false
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.delegate = self
....
// MARK: - CLLocationManagerDelegate
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
print ("locationManager: didChangeAuthorization called")
if (CLLocationManager.locationServicesEnabled()) {
switch status {
case .notDetermined:
// Request when-in-use authorization initially
locationManager.requestWhenInUseAuthorization()
print ("locationManager: notDetermined & requestWhenInUseAuthorization")
break
case .authorizedWhenInUse:
// Enable basic location features
locationManager.startUpdatingLocation()
print ("locationManager: authorizedWhenInUse & startUpdatingLocation")
break
case .authorizedAlways:
// Enable any of your app's location features
//enableMyAlwaysFeatures()
break
case .restricted, .denied:
//determine if system or app loc svcs disabled
print ("locationManager: restricted or denied")
noAppLocationService()
break
#unknown default:
print("locationManager: unknown authorization state")
}
}else{
viewOnlyMode()
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let GPSAccuracy:CLLocation = locations[0] as CLLocation
print ("locationManager: didUpdateLocations")
if let location = locations.last?.coordinate {
if (currentLocation.latitude != location.latitude) || (currentLocation.longitude != location.longitude) {
self.currentLocation = location
GPSHorizontalAccuracy = GPSAccuracy.horizontalAccuracy
// print("LocManAccuracy: \(GPSAccuracy.horizontalAccuracy)")
// print("LocManLatitude: \(GPSAccuracy.coordinate.latitude)")
// print("LocManLongitude: \(GPSAccuracy.coordinate.longitude)")
// print("LocManCurrLat: \(currentLocation.latitude)")
// print("LocManCurrLong: \(currentLocation.longitude)")
if firstMapLoad {
// Set the map’s center coordinate and zoom level.
let camera = GMSCameraPosition.camera(withTarget: self.currentLocation, zoom: 13)
self.viewMap?.animate(to: camera)
firstMapLoad = false;
}
}
}
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("Location Error = \(error.localizedDescription)")
}
When I run it on the iPhone 11 Pro Max simulator in Xcode, if the iPhone simulator has been reset and run the app for the first time I get the authorization alert with the 3 choices. I select "when in use" and the app works fine - the didChangeAuthorization function is called twice (once when location manager is initialized and then when I select "when in use"). didUpdateLocations is then called and the app gets location updates.
If I stop the app, delete it from the simulator and then re-run from Xcode the app does not request user permission for location services. didChangeAuthorization is not called when the location manager is initialized and thus location services are not started and the app doesn't receive any location updates. I have observed the same behavior on a real iPhone 11 Pro.
I tried setting the permission for the app to "never" in the app location settings, stopped the app and then deleted the app on the simulator. When I ran from Xcode the next time the app did not ask for location permissions, but did display an alert that location services were disabled. It appears that the settings from the previous installation were retained even though the app was deleted.
In my case, the delegate's method signature was wrong for iOS 14+
iOS <=13, deprecated in iOS 14
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
iOS 14+
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager)
If you're targeting iOS <14, you should implement both

How do I make Location permission request trigger only when the user clicks on the map tab in a UITabBar?

I am building an app using UITabBar and one of the tab items is a map. I only want the user to have to respond to the LocationService() request when they tap on the map tab. However, when the app loads to the tabBar, the location permission request pops up first thing.
Here is the code for the LocationService()
import CoreLocation
protocol LocationServiceDelegate: class {
func authorizationDenied()
func setMapRegion(center: CLLocation)
}
class LocationService: NSObject {
var locationManager = CLLocationManager()
weak var delegate: LocationServiceDelegate?
override init() {
super.init()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
}
private func checkAuthorizationStatus() {
switch CLLocationManager.authorizationStatus() {
case .notDetermined:
locationManager.requestAlwaysAuthorization()
case .denied:
delegate?.authorizationDenied()
case .authorizedAlways, .authorizedWhenInUse:
startUpdatingLocation()
default:
break
}
}
private func startUpdatingLocation() {
locationManager.startUpdatingLocation()
}
}
extension LocationService: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
checkAuthorizationStatus()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
locationManager.stopUpdatingLocation()
if let location = locations.last {
delegate?.setMapRegion(center: location)
}
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print(error.localizedDescription)
}
}
The method was originally called in viewDidLoad so the map would center on the user's location, so I moved it to viewDidAppear, but I still get the same notice when the app launches.
How do I delay the permission request until the user actually taps on the map tab - in this case the DIY Stores tab?

GameCenter not working, authentication and leaderboard not showing

With Swift 2, GameCenter is not working for me. The authentication ViewController is not showing up... Here is my func authenticateLocalPlayer():
func authenticateLocalPlayer() {
var localPlayer = GKLocalPlayer()
localPlayer.authenticateHandler = {(viewController: UIViewController?, error: NSError?) -> Void in
if (viewController != nil) {
self.presentViewController(viewController!, animated: true, completion: nil)
print("Not Authenticated. ")
} else {
print("Authenticated. ")
}
}
}
It is returning "Not Authenticated" every time, but is not presenting the ViewController. Any solution?
This solution presents the viewController correctly using Swift 2 in Xcode 7.0.
Note that I have changed the code before the if statement begins. I believe the syntax may have changed in a recent software update as I had this problem too.
In my app I called authenticateLocalPlayer() in the viewDidLoad() method of the GameViewController class.
func authenticateLocalPlayer() {
let localPlayer = GKLocalPlayer.localPlayer()
localPlayer.authenticateHandler = {(viewController, error) -> Void in
if (viewController != nil) {
self.presentViewController(viewController!, animated: true, completion: nil)
}
else {
print((GKLocalPlayer.localPlayer().authenticated))
}
}
}

Segues in Swift

im new to swift / xcode. I am trying to set up a facebook login.
The login works fine but when the login is successful the segue doesnt appear to work. There are no errors it just doesnt go to the next viewcontroller.
I suspect the issue lies here somehow:
self.performSegueWithIdentifier("showNew", sender: self)
any ideas?
import UIKit
import FBSDKCoreKit
import FBSDKLoginKit
class ViewController: UIViewController, FBSDKLoginButtonDelegate {
override func viewDidLoad() {
super.viewDidLoad()
if (FBSDKAccessToken.currentAccessToken()==nil){
println("not Logged in")
}
else{
println("Logged in!")
self.performSegueWithIdentifier("showNew", sender: self)
}
var loginButton = FBSDKLoginButton()
loginButton.readPermissions = ["public_profile","email","user_friends"]
loginButton.center = self.view.center
loginButton.delegate = self
self.view.addSubview(loginButton)
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!) {
if error == nil {
println("Login Complete")
}
else
{
println(error.localizedDescription)
}
}
func loginButtonDidLogOut(loginButton: FBSDKLoginButton!) {
println("User Logged Out!")
}
}
Your forgot to declare the identifier.
I assume that you want the app to move to next view controller after the FB login. Basically move on login success.
Move
self.performSegueWithIdentifier("showNew", sender: self)
to loginButton delegate.
func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!)
{
if (error == nil)
{
println("Login Complete")
self.performSegueWithIdentifier("showNew", sender: self)
}
else
{
println(error.localizedDescription)
}
}
If your segue was not defined properly, the app would have crashed. Since it is not crashing at self.performSegueWithIdentifier, you can believe that it is defined.

Resources