• Stars
    star
    3,334
  • Rank 12,855 (Top 0.3 %)
  • Language
    Swift
  • License
    MIT License
  • Created almost 9 years ago
  • Updated about 2 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

⚓️ Async/Await CLLocationManager Wrapper for Apple Platforms

logo-library

Platform Swift Swift Package Manager

SwiftLocation is a lightweight wrapper around Apple's CoreLocation framework that supports the new Swift Concurrency model.

This means no more delegate pattern to deal with, nor completion blocks.
You can manage location requests, region, and beacon monitoring directly using the new async/await syntax.

Would you, for example, get the current user location?
It's just 2 lines code away:

try await location.requestPermission(.whenInUse) // obtain the permissions
let userLocation = try await location.requestLocation() // get the location

How it works

SwiftLocation is quite straightforward to use.
Simply create your own Location instance and use one of the available methods.

Important

Some APIs may not available under some of the supported platforms due to specific hardware constraints.

What's new in 6.0

The new 6.0 milestone is a completely rewritten version designed to support async/await optimally. We are also focused on supporting all CoreLocation features without creating an overwhelmed package.
All the features are supported by a complete unit tests suite.

This new version is also distributed only via Swift Package Manager (5.5+) and it's compatible with all the Apple Platforms: iOS 14+, macOS 11+, watchOS 7+, tvOS 14+.

The features from version 5.x - geocoding, ip resolve, autocomplete - will be included as separate downloadable modules later in the development process.

Service Location Status

Use the location.locationServicesEnabled to get the current status of the location services.
In order to monitor changes you can use the AsyncStream's startMonitoringLocationServices()` method:

for await event in await location.startMonitoringLocationServices() {
 print("Location Services are \(event.isLocationEnabled ? "enabled" : "disabled")"
 // break to interrupt the stream
}

You can stop the stream at any moment using break; it will call the stopMonitoringLocationServices() automatically on used `Location`` instance.

Authorization Status

You can obtain the current status of the authorization status by using the location.authorizationStatus property.
If you need to monitor changes to this value you can use the AsyncStream offered by startMonitoringAuthorization() method:

for await event in await location.startMonitoringAuthorization() {
  print("Authorization status did change: \(event.authorizationStatus)")
  // break to interrupt the stream
}

Accuracy Authorization Level

The location.accuracyAuthorization offers a one shot value of the current precision level offered by your application.
When you need to monitor changes you can use the AsyncStream offered by startMonitoringAccuracyAuthorization():

for await event in await location.startMonitoringAccuracyAuthorization() {
  print("Accuracy authorization did change: \(event.accuracyAuthorization.description)")
  // break to interrupt the stream
}

Request Location Permission

Also the request location permission is managed via async await. You can use the requestPermission() method once you have properly configured your Info.plist file:

// return obtained CLAuthorizationStatus level
let obtaninedStatus = try await location.requestPermission(.whenInUse)

Provide descriptions of how you use location services

The first time you make an authorization request, the system displays an alert asking the person to grant or deny the request. The alert includes a usage description string that explains why you want access to location data.

You provide this string in your app’s Info.plist file and use it to inform people about how your app uses location data.

Core Location supports different usage strings for each access level. You must include a usage description string for When in Use access. If your app supports Always access, provide an additional string explaining why you want the elevated privileges. The following table lists the keys to include in your Info.plist and when to include them.

Usage key Required when:
NSLocationWhenInUseUsageDescription The app requests When in Use or Always authorization.
NSLocationAlwaysAndWhenInUseUsageDescription The app requests Always authorization.
NSLocationTemporaryUsageDescriptionDictionary Used when you want to temporary extend the precision of your authorization level

Request Temporary Precision Permission

If the App does not require an exact location for all of its features, but it is required to have accurate one only for specific features (i.e during checkout, booking service, etc) — then App may ask for temporary accuracy level for that session only using the requestTemporaryPrecisionAuthorization(purpose:) method:

// return CLAccuracyAuthorization value
let status = try await location.requestTemporaryPrecisionAuthorization(purpose: "booking")

Continous Location Monitoring

If you need to continous monitoring new locations from user's device you can use the AsyncStream offered by startMonitoringLocations():

for await event in try await location.startMonitoringLocations() {
    switch event {
    case .didPaused:
	// location updates paused
    case .didResume:
    // location updates resumed
    case let .didUpdateLocations(locations):
    // new locations received   
    case let .didFailed(error):
    // an error has occurred   
    }
    // break to stop the stream
}

Request One-Shot User Location

Sometimes you may need to get the user location as single value. The async's requestLocation(accuracy:timeout:) method was created to return an optionally filtered location within a valid time interval:

// Simple implementation to get the last user location
let location = try await location.requestLocation()

// Optionally you can return a value only if satisfy one or more constraints
let location = try await location.requestLocation(accuracy: [
    .horizontal(100) // has an horizontal accuracy of 100 meters or lower
], timeout: 8) // wait for response for a max of 8 seconds

Filters include horizontal/vertical, speed, course accuracy and it offer the opportunity to set a custom filter functions as callback.

Visits Monitoring

Visits monitoring allows you to observe places that the user has been.
Visit objects are created by the system and delivered by the CLLocationManager. The visit includes the location where the visit occurred and information about the arrival and departure times as relevant.

To monitor visits you can use the AsyncStream's startMonitoringVisits() method:

for await event in await location.startMonitoringVisits() {
    switch event {
    case let .didVisit(place):
    // a new CLVisit object has been received.   
    case let .didFailWithError(error):
    // an error has occurred
    }
}

Significant Location Changes Monitoring

The AsyncStream's startMonitoringSignificantLocationChanges() method starts the generation of updates based on significant location changes.

for await event in await self.location.startMonitoringSignificantLocationChanges() {
    switch event {
    case .didPaused:
    // stream paused
    case .didResume:
    // stream resumed
    case .didUpdateLocations(locations):
    // new locations received
    case let .didFailWithError(error):
    // an error has occured
    }
	// break to stop the stream
}

Device Heading Monitoring

To get updates about the current device's heading use the AsyncStream offered by startUpdatingHeading() method:

for await event in await self.location.startUpdatingHeading() {
	// a new heading value has been generated
}

Beacon Ranging

Beacon ranging is offered by the AsyncStream's startRangingBeacons() method:

let constraint: CLBeaconIdentityConstraint = ...
for await event in await location.startRangingBeacons(satisfying: constraint) {
	// a new event has been generated
}

Testing Suite & Mocked CLLocationManager

SwiftLocation is distribuited with an extensive unit testing suite you can found into the SwiftLocationTests folder.
Inside the suite you will also found the MockedLocationManager.swift file which is a CLLocationManager mock class you can use to provide the testing suite for your application. By configuring and extending this file you will be able to mock results of location requests and monitoring directly in your host app.

Installation via SPM

SwiftLocation is offered via Swift Package Manager.
Add it as a dependency in a Swift Package, and add it to your Package.swift:

dependencies: [
  .package(url: "https://github.com/malcommac/SwiftLocation.git", from: "6.0.0")
]

Support This Work ❤️

If you love this library and wanna encourage further development consider becoming a sponsor of my work via Github Sponsorship.

License

This package was created and maintaned by Daniele Margutti.

It was distribuited using MIT License.

Contributing

  • If you need help or you'd like to ask a general question, open an issue.
  • If you found a bug, open an issue.
  • If you have a feature request, open an issue.
  • If you want to contribute, submit a pull request.

Read the CONTRIBUTING file for more informations.

More Repositories

1

SwiftDate

🐔 Toolkit to parse, validate, manipulate, compare and display dates, time & timezones in Swift.
Swift
7,500
star
2

SwiftRichString

👩‍🎨 Elegant Attributed String composition in Swift sauce
Swift
3,046
star
3

Hydra

⚡️ Lightweight full-featured Promises, Async & Await Library in Swift
Swift
1,971
star
4

Repeat

🕦 Modern Timer in Swift, Debouncer and Throttler (alternative to NSTimer) made with GCD
Swift
1,456
star
5

UIWindowTransitions

🏃‍♂️ Animated transitions for UIWindow's rootViewController property
Swift
465
star
6

ImageSizeFetcher

Finds the type/size of an image given its URL by fetching as little data as needed
Swift
442
star
7

Owl

A declarative type-safe framework for building fast and flexible lists with UITableViews & UICollectionViews
Swift
434
star
8

ScrollStackController

🧩 Easy scrollable layouts in UIKit - an UIStackView which scroll and uses root views of child view controllers.
Swift
426
star
9

Flow

Declarative approach to populate and manage UITableViews (see https://github.com/malcommac/FlowKit)
Swift
423
star
10

SwiftSimplify

🥷 High-performance polyline simplification library - port of simplify.js
Swift
293
star
11

DMLazyScrollView

Lazy Loading UIScrollView for iOS (with support for infinite scrolling)
Objective-C
293
star
12

DMPagerViewController

DMPagerViewController is page navigation controller like the one used in Twitter or Tinder
Objective-C
278
star
13

FlowKit

A declarative type-safe framework for building fast and flexible list with Tables & Collection
Swift
211
star
14

DMCircularScrollView

Infinite/Circular Scrolling Implementation for UIScrollView
Objective-C
205
star
15

ScrollingStackContainer

Efficient Scrolling UIStackView in Swift - DEPRECATED (use ScrollStackController)
Swift
198
star
16

SwiftScanner

String Scanner in pure Swift (supports unicode)
Swift
171
star
17

SwiftMsgPack

💬 Fast & Lightweight MsgPack Serializer & Deserializer for Swift
Swift
154
star
18

DMSlidingCell

Swipe To Reveal UITableViewCell Implementation as like in Twitter
Objective-C
152
star
19

DMSplitView

New NSSplitView class with multiple subviews resize behaviors and animated transitions
Objective-C
116
star
20

DMScrollingTicker

Advanced horizontal scrolling ticker for iOS
Objective-C
110
star
21

DMDynamicWaterfall

UICollectionView Waterfall Layout with UIKit Dynamics
Objective-C
109
star
22

DMTabBar

XCode 4.x like inspector segmented control
Objective-C
108
star
23

HermesNetwork

Swift
73
star
24

DMInspectorPalette

Animated NSScrollView with collapsible sections like in XCode Inspector
Objective-C
61
star
25

SwiftUnistroke

✍️ $1 Unistroke Gesture Recognizer in Swift
Swift
53
star
26

UAParserSwift

🗺 User-Agent Parser based upon ua-parser.js
Swift
39
star
27

DMPageControl

An high customizable alternative to UIPageControl
39
star
28

DMTwitterOAuth

Twitter OAuth Library (Callback URL Login)
Objective-C
37
star
29

DMScrollViewStack

DMScrollViewStack is a UIScrollView subclass that efficiently handles a vertical stack of multiple scrollviews
Objective-C
33
star
30

DMLocationManager

Location Manager for iOS made simple
Objective-C
27
star
31

DMPathBar

XCode's Yosemite like path bar of OS X
Objective-C
25
star
32

Swift-Coding-Guidelines

A repository to collect best practices when programming with Swift
20
star
33

xcbetarunner

Run & Debug projects [easily] with stable Xcode on beta iOS devices
Swift
17
star
34

GitLabSwift

🛵 Async/Await GitLab REST APIs v4 for Swift
Swift
14
star
35

DMCacheBox

Fast advanced caching system for Objective-C (Cocoa/iOS compatible)
Objective-C
14
star
36

RealEventsBus

🚎 Simple type-safe event bus implementation in swift
Swift
13
star
37

DMMultiDelegatesProxy

Multiple delegate architecture made using NSProxy
Objective-C
10
star
38

Glider-Old

✈️ Fast & powerful logger for Swift
Swift
9
star
39

NSSplitView-Animatable

NSSplitView Category to perform simple animations with dividers
Objective-C
9
star
40

CircularScroller

Efficient and Lightweight endless UIScrollView implementation in Swift
Swift
7
star
41

DMAPNServer

APN - Apple Push Notification Server in PHP
PHP
6
star
42

DMCoreDataUtils

Utilities methods for Apple's Core Data Storage
Objective-C
6
star
43

SlidingSheet

Configurable Bottom Sheet for UIKit - like AirBnb and Apple Maps
Swift
4
star
44

sentry-cocoa-sdk-xcframeworks

A mirror for https://github.com/getsentry/sentry-cocoa to add support for binary (xcframework) distribution with swift package manager.
Shell
4
star
45

CAKeyFrameAnimation-Evaluators

Easily specify CAKeyFrameAnimation curves using C functions or ObjC Class
Objective-C
3
star
46

ZoomableListController

Apple's iOS Weather App List Imitation written in Swift
Swift
2
star
47

MeetingBot

Your next call on Mac status bar
Swift
2
star
48

Konsole

In-app Swift tools for great iOS developers
1
star
49

DMGrid

A simple 2D Grid class made in Objective-C
Objective-C
1
star
50

Envy

Type safe environment variables from shell processes and .env files
1
star