------------------------- | Location Tracker | |-----------------------| | Latitude: ---.------ | | Longitude: ---.------ | | | | [Start Tracking] | -------------------------
Location services (Core Location) in iOS Swift - Mini App: Build & Ship
import UIKit import CoreLocation class LocationTrackerViewController: UIViewController { let locationManager = CLLocationManager() let latitudeLabel = UILabel() let longitudeLabel = UILabel() let startButton = UIButton(type: .system) override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .white // Setup UI latitudeLabel.text = "Latitude: ---.------" longitudeLabel.text = "Longitude: ---.------" startButton.setTitle("Start Tracking", for: .normal) latitudeLabel.translatesAutoresizingMaskIntoConstraints = false longitudeLabel.translatesAutoresizingMaskIntoConstraints = false startButton.translatesAutoresizingMaskIntoConstraints = false view.addSubview(latitudeLabel) view.addSubview(longitudeLabel) view.addSubview(startButton) NSLayoutConstraint.activate([ latitudeLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor), latitudeLabel.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 100), longitudeLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor), longitudeLabel.topAnchor.constraint(equalTo: latitudeLabel.bottomAnchor, constant: 20), startButton.centerXAnchor.constraint(equalTo: view.centerXAnchor), startButton.topAnchor.constraint(equalTo: longitudeLabel.bottomAnchor, constant: 40) ]) // TODO: Add your code here }
import UIKit import CoreLocation class LocationTrackerViewController: UIViewController, CLLocationManagerDelegate { let locationManager = CLLocationManager() let latitudeLabel = UILabel() let longitudeLabel = UILabel() let startButton = UIButton(type: .system) override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .white latitudeLabel.text = "Latitude: ---.------" longitudeLabel.text = "Longitude: ---.------" startButton.setTitle("Start Tracking", for: .normal) latitudeLabel.translatesAutoresizingMaskIntoConstraints = false longitudeLabel.translatesAutoresizingMaskIntoConstraints = false startButton.translatesAutoresizingMaskIntoConstraints = false view.addSubview(latitudeLabel) view.addSubview(longitudeLabel) view.addSubview(startButton) NSLayoutConstraint.activate([ latitudeLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor), latitudeLabel.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 100), longitudeLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor), longitudeLabel.topAnchor.constraint(equalTo: latitudeLabel.bottomAnchor, constant: 20), startButton.centerXAnchor.constraint(equalTo: view.centerXAnchor), startButton.topAnchor.constraint(equalTo: longitudeLabel.bottomAnchor, constant: 40) ]) locationManager.delegate = self locationManager.desiredAccuracy = kCLLocationAccuracyBest startButton.addTarget(self, action: #selector(startTracking), for: .touchUpInside) checkLocationAuthorization() } func checkLocationAuthorization() { switch CLLocationManager.authorizationStatus() { case .notDetermined: locationManager.requestWhenInUseAuthorization() case .restricted, .denied: showPermissionDeniedAlert() case .authorizedWhenInUse, .authorizedAlways: // Permission granted, do nothing yet break @unknown default: break } } @objc func startTracking() { if CLLocationManager.locationServicesEnabled() { locationManager.startUpdatingLocation() } else { showPermissionDeniedAlert() } } func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { guard let location = locations.last else { return } latitudeLabel.text = String(format: "Latitude: %.6f", location.coordinate.latitude) longitudeLabel.text = String(format: "Longitude: %.6f", location.coordinate.longitude) } func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) { checkLocationAuthorization() } func showPermissionDeniedAlert() { let alert = UIAlertController(title: "Location Permission Denied", message: "Please enable location permissions in Settings to use this feature.", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "OK", style: .default)) present(alert, animated: true) } }
This app uses Core Location to get the user's current position. We first ask for permission to access location data. If permission is denied, we show an alert to inform the user.
The startButton triggers location updates. When the location changes, the delegate method updates the latitude and longitude labels with the new coordinates.
We use CLLocationManagerDelegate to handle location updates and authorization changes. The UI is simple and centered, showing the coordinates clearly.
------------------------- | Location Tracker | |-----------------------| | Latitude: 37.774929 | | Longitude: -122.419416| | | | [Start Tracking] | -------------------------
Practice
What is the main purpose of CLLocationManager in iOS apps?
Solution
Step 1: Understand the role of CLLocationManager
CLLocationManageris designed to get location data from the device's GPS or other sources.Step 2: Differentiate from other classes
Displaying maps is done byMKMapView, notifications byUNUserNotificationCenter, and network requests byURLSession.Final Answer:
To request and receive location updates from the device -> Option AQuick Check:
CLLocationManager = Location updates [OK]
- Confusing CLLocationManager with map display classes
- Thinking it handles notifications or networking
- Assuming it works without user permission
Which of the following is the correct way to declare a CLLocationManager instance in Swift?
?
Solution
Step 1: Recall Swift instance creation syntax
In Swift, to create an instance, uselet variable = ClassName()orvar variable = ClassName().Step 2: Check each option
let locationManager = CLLocationManager() correctly creates a constant instance. var locationManager: CLLocationManager declares a variable without initialization, which is incomplete. locationManager = CLLocationManager() misses declaration keyword. CLLocationManager locationManager = new CLLocationManager() uses incorrect syntax from other languages.Final Answer:
let locationManager = CLLocationManager() -> Option CQuick Check:
Swift instance creation = let variable = Class() [OK]
- Forgetting to initialize the variable
- Using syntax from other languages like Java or C#
- Missing let or var keyword
Given the following Swift code snippet, what will be printed when the location updates?
class LocationHandler: NSObject, CLLocationManagerDelegate {
let manager = CLLocationManager()
override init() {
super.init()
manager.delegate = self
manager.requestWhenInUseAuthorization()
manager.startUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.first {
print("Lat: \(location.coordinate.latitude), Lon: \(location.coordinate.longitude)")
}
}
}
let handler = LocationHandler()Solution
Step 1: Analyze delegate setup and method
The delegate is set to self, and the required methodlocationManager(_:didUpdateLocations:)is implemented to print coordinates.Step 2: Understand permission and update calls
The code requests permission and starts location updates, so when location is available, it prints latitude and longitude.Final Answer:
It prints the latitude and longitude of the first location update -> Option BQuick Check:
Delegate set + method implemented = prints location [OK]
- Assuming delegate is not set
- Thinking permission request blocks printing
- Missing delegate method causes crash
What is wrong with this Swift code snippet for requesting location updates?
let locationManager = CLLocationManager() locationManager.startUpdatingLocation()
Solution
Step 1: Check for permission request
The code does not request user permission, which is required before starting location updates.Step 2: Check delegate assignment
Without setting a delegate, the app cannot receive location updates callbacks.Final Answer:
It is missing setting the delegate and requesting user permission -> Option AQuick Check:
Permission + delegate needed before updates [OK]
- Calling startUpdatingLocation without permission
- Not assigning delegate to receive updates
- Thinking startUpdatingLocation is invalid
You want your app to get the user's location only once and then stop updates to save battery. Which code snippet correctly does this?
class SingleLocationFetcher: NSObject, CLLocationManagerDelegate {
let manager = CLLocationManager()
override init() {
super.init()
manager.delegate = self
manager.requestWhenInUseAuthorization()
manager.startUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.first {
print("Got location: \(location.coordinate.latitude), \(location.coordinate.longitude)")
manager.stopUpdatingLocation()
}
}
}Solution
Step 1: Check when stopUpdatingLocation is called
The methodlocationManager(_:didUpdateLocations:)callsstopUpdatingLocation()after receiving the first location, stopping further updates.Step 2: Verify permission and delegate setup
The code requests 'when in use' authorization and sets the delegate properly, so it will work as intended.Final Answer:
This code correctly stops updates after receiving the first location -> Option DQuick Check:
Stop updates inside didUpdateLocations = single fetch [OK]
- Calling stopUpdatingLocation before receiving location
- Confusing background permission with when-in-use
- Not setting delegate before starting updates
Ready to prove it?
Pass the test and this pattern moves unknown
