How to use CoreLocation with swift? - ios

I've tried using CoreLocation with my Swift app, but without luck. I have the following incredibly simple code:
(I've linked the CoreLocation library.)
import UIKit
import CoreLocation
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate {
var window: UIWindow?
var locationManager: CLLocationManager = CLLocationManager()
locationManager.delegate = self
On the last line I get the error "Expected declaration."
What am I doing wrong?
Thanks in advance!

The following code locationManager.delegate = self is a statement. You need to execute it within one of the AppDelegate methods. For example:
class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate {
var window: UIWindow?
var locationManager: CLLocationManager = CLLocationManager()
func application(application :UIApplication, didFinishLaunchingWithOptions launchOptions:NSDictionary>) -> Bool {
locationManager.delegate = self
}
}

Related

SwiftUI AppDelegate UIWindow redeclaration

I'm using SwiftUI so the AppDelegate is added by
#UIApplicationDelegateAdaptor(MyAppDelegate.self) var myAppDelegate
All delegate callbacks work fine, but var window: UIWindow? can't be redeclared.
Adding it to MyAppDelegate has no effect as if accessing UIApplication.shared.delegate class is not MyAppDelegate but SwiftUI.AppDlegate.
How I can add it to AppDelegate, to make it accessible by UIApplication.shared.delegate.window ?
Or how to set var window: UIWindow? property to SwiftUI.AppDlegate ?
Solution found. Custom MyAppDelegate can contain var window: UIWindow? property:
class MyAppDelegate: NSObject, ObservableObject, UIApplicationDelegate {
var window: UIWindow?
}
And can be accessed by EnvironmentVariable:
#EnvironmentObject private var appDelegate: MyAppDelegate
appDelegate.window = <Window object>
Then the correct UIWindow value will be available by UIApplication.shared.delegate.window
Documentation refference: https://developer.apple.com/documentation/swiftui/uiapplicationdelegateadaptor

Google Maps iOS SDK

This is my code
import UIKit
import GooglePlaces
import GoogleMaps
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
GMSPlacesClient.provideAPIKey("************************")
GMSServices.provideAPIKey("************************")
return true
}
but I'm still getting the exception
Terminating app due to uncaught exception 'GMSServicesException',
reason: 'Google Maps SDK for iOS must be initialized via [GMSServices
provideAPIKey:...] prior to use'
Is there any other cause, help me to fix it.
ViewController class is calling before appDelegate. So, the APIKey was not initiated. After finding this I initiate the viewController in appDelegate.
You must add API Key in App delegate and implement GoogleMap delegate in ViewController
import UIKit
import GoogleMaps
let googleApiKey = "<YOUR API Key HERE>"
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
GMSServices.provideAPIKey(googleApiKey)
return true
}
//other methods
}
and your ViewController should be like
import UIKit
import GoogleMaps
class ViewController: UIViewController, CLLocationManagerDelegate {
private let locationManager = CLLocationManager()
#IBOutlet weak var mapView: GMSMapView!
override func viewDidLoad() {
super.viewDidLoad()
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
}
// MARK: - CLLocationManagerDelegate
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
guard status == .authorizedWhenInUse else {
return
}
locationManager.startUpdatingLocation()
mapView.isMyLocationEnabled = true
mapView.settings.myLocationButton = true
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let location = locations.first else {
return
}
mapView.camera = GMSCameraPosition(target: location.coordinate, zoom: 15, bearing: 0, viewingAngle: 0)
locationManager.stopUpdatingLocation()
}
}
PS: Make sure you don't forget these important steps.
Go to Google Developers Console and create app and API Key
Enable APIs for Google Maps SDK for iOS
Add privacy permissions in .Plist file
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Application requires user’s location information while the app is running in the foreground.</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>Will you allow this app to always know your location?</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Do you allow this app to know your current location?</string>

IOS Location Updates in background mode stops when I use safari or other apps

I have enabled location services under capabilities for background mode, everything works fine if I click the home button, I get the updates. I even get updates when using safari until I go on facebook or something, it just stops. The app hasn't crashed or anything and It doesn't consume much memory nor does it drain alot of power. My app has an NSTimer which only requires the location after every 30 seconds.
App Delegate:
import UIKit
import CoreLocation
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate {
var window: UIWindow?
var manager = CLLocationManager()
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
manager.desiredAccuracy = kCLLocationAccuracyThreeKilometers
manager.delegate = self
manager.requestAlwaysAuthorization()
manager.startUpdatingLocation()
return true
}
Main View Controller:
import UIKit
import CoreLocation
class MainViewController: UIViewController, SettingsViewDelegate {
#IBOutlet weak var pageMenuView: UIView!
var audioPlayer = AVAudioPlayer()
var lastTimestamp: NSDate!
var timer : NSTimer?
lazy var locationManager: CLLocationManager = {
var _locationManager = CLLocationManager()
_locationManager.delegate = self
_locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers
// Movement threshold for new events
return _locationManager
}()
override func viewDidLoad() {
super.viewDidLoad()
self.timer = NSTimer.scheduledTimerWithTimeInterval(30, target: self, selector: #selector(MainViewController.startLocationUpdates), userInfo: nil, repeats: true)
}
func startLocationUpdates() {
// Here, the location manager will be lazily instantiated
locationManager.startUpdatingLocation()
}
}
// MARK: - CLLocationManagerDelegate
extension MainViewController: CLLocationManagerDelegate {
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print("location \(reminderTime)")
self.locationManager.stopUpdatingLocation()
}
}
Update:
This issue happens on the physical device, iphone 5c

Swift - App Delegate not passing data

I'm developing an App that it's data is from a URL, here's a sample code that I'm using
AppDelegate.swift
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var fromUrl: String!
func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject)-> Bool {
print("Host: \(url.host!)")
self.fromUrl = url.host!
return true
}
ViewController.swift
import UIKit
class ViewController: UIViewController {
let appDelegate = AppDelegate()
override func viewDidLoad() {
super.viewDidLoad()
print(appDelegate.fromUrl)
}
It's is logging the url.host from app delegate. But when i try to log the value of fromUrl from the ViewController.swift it's returning nil. What do you think seems to be the problem? Thanks!
When you declare let appDelegate = AppDelegate() in ViewController you are actually instantiating another instance of AppDelegate. That is not the same instance that you are using as you actual ApplicationDelegate. Try getting that reference by using:
if let appDelegate = UIApplication.sharedApplication().delegate as? AppDelegate {
print(appDelegate.fromUrl)
}

Where to initialize the base class of my app in Swift

I have a class named Home which is the parent class of my app. Now, I want to initialize this class somewhere so that I can access everything inside the class from wherever I want. The starting point of the app is RootViewController. Should I initialize the app in the starting point? If yes, how should I do it so that it can be accessed from everywhere in the app?
As per my comment above, set a property on the AppDelegate class with the type Home, initialize it in application:didFinishLaunchingWithOptions. Now you can access this instance of home through the sharedApplication.delegate.
In AppDelegate.swift:
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var myHome: Home?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
// Override point for customization after application launch.
self.myHome = Home()
return true
}
Then access it in some other class:
let delegate = UIApplication.sharedApplication().delegate as AppDelegate
var home = delegate.myHome

Resources