SwiftLocation is a lightweight library you can use to monitor locations, make reverse geocoding (both with Apple and Google's services) monitor beacons and do beacon advertising. It's really easy to use and it's compatible both with Swift 2.2, 2.3 and 3.0.
★★ Star our GitHub repository to help us! ★★
Pick the right version:
- Swift 3.0 is in master (and develop) (CocoaPods Tag >= 1.0.6)
- Old/Unsupported Swift 2.2 branch is here. (CocoaPods Tag = 1.0.5)
- Old/Unsupported Swift 2.3 branch is here.
- Old/Unsupported Swift 2.0 branch is here
Main features includes:
- Auto Management of hardware resources: SwiftLocation turns off hardware if not used by our observers. Don't worry, we take care of your user's battery usage!
- Complete location monitoring: you can easily monitor for your desired accuracy and frequency (continous monitoring, background monitoring, monitor by distance intervals, interesting places or significant locations).
- Device's heading observer: you can observe or get current device's heading easily
- Reverse geocoding (from address string/coordinates to placemark) using both Apple and Google services (with support for API key)
- GPS-less location fetching using network IP address
- Geographic region monitoring (enter/exit from regions)
- Beacon Family and Beacon monitoring
- Set a device to act like a Beacon (only in foreground)
Before using SwiftLocation you must configure your project to use location services. First of all you need to specify a value for NSLocationAlwaysUsageDescription
or NSLocationWhenInUseUsageDescription
into your application's Info.plist file. The string value you add will be shown along with the authorization request the first time your app will try to use location services hardware.
If you need background monitoring you should specify NSLocationAlwaysUsageDescription
and specify the correct value in UIBackgroundModes
key (you can learn more here)
I'm collecting all the apps which uses SwiftLocation to manage beacon or location. If you are using SwiftLocation in your project please fill a PR to this file or send an email to hello@danielemargutti.com.
- Monitor Current User Location (one shout, continous delivery etc.)
- Obtain Current Location without GPS
- Monitor Device Heading
- Reverse Address/Coordinates to CLPlacemark
- Monitor Interesting Visits
- Monitor Geographic Regions
- Monitor Beacons & Beacon Families
- Act like a Beacon
- Observe CLLocationManager Auth Events
Getting current user's location is pretty easy; all location related services are provided by the LocationManager
singleton class.
Location.getLocation(withAccuracy: .Block, onSuccess: { foundLocation in
// Your desidered location is here
}) { (lastValidLocation, error) in
// something bad has occurred
// - error contains the error occurred
// - lastValidLocation is the last found location (if any) regardless specified accuracy level
}
When you create a new observer you will get a request object LocationRequest
you can use to change on the fly the current observer configuration or stop it.
This is an example:
Location.getLocation(withAccuracy: .Block, frequency: .OneShot, timeout: 50, onSuccess: { (location) in
// You will receive at max one event if desidered accuracy can be achieved; this because you have set .OneShot as frequency.
}) { (lastValidLocation, error) in
}
// Sometimes in the future
request.stop() // Stop receiving updates
request.pause() // Temporary pause events
request.start() // Restart a paused request
LocationRequest
also specify a timeout
property you can set to abort the request itself if no valid data is received in a certain amount of time. By default it's set to 30 seconds
(you can change directly at init time in getLocation()
functions or by changing the .timeout
property of the request itself)
Location.getLocation()
lets you to specify two parameters: the accuracy
you need to get and the frequency
intervals you want to use to get updated locations.
ACCURACY:
IPScan
: (Network connection is required). Get an approximate location by using device's IP address. It does not require GPS sensor or user authorizations.Any
: First available location is accepted, no matter the accuracyCountry
: Only locations accurate to the nearest 100 kilometers are dispatchedCity
: Only locations accurate to the nearest three kilometers are dispatchedNeighborhood
: Only locations accurate to the nearest kilometer are dispatchedBlock
: Only locations accurate to the nearest one hundred meters are dispatchedHouse
: Only locations accurate to the nearest ten meters are dispatchedRoom
: Use the highest-level of accuracy, may use high energyNavigation
: Use the highest possible accuracy and combine it with additional sensor data
FREQUENCY:
Continuous
: receive each new valid location, never stop (you must stop it manually)OneShot
: the first valid location data is received, then the request will be invalidatedByDistanceintervals(meters)
: receive a new update each time a new distance interval is travelled. Useful to keep battery usage lowSignificant
: receive only valid significant location updates. This capability provides tremendous power savings for apps that want to track a user’s approximate location and do not need highly accurate position information
Sometimes you could need to get the current approximate location and you may not need to turn on GPS hardware and waste user's battery. When accuracy is not required you can locate the user by it's public network IP address (obviously this require an internet connection).
Location.getLocation(withAccuracy: .IPScan, onSuccess: { (location) in
// approximate location is here
}) { (lastValidLocation, error) in
// something wrong has occurred; error will tell you what
}
To be able to find user's location this way, you need to update your info.plist
and add required security settings for it. (iOS 9+):
<dict>
<key>NSAllowsArbitraryLoads</key>
<false/>
<key>NSExceptionDomains</key>
<dict>
<key>ip-api.com</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSTemporaryExceptionMinimumTLSVersion</key>
<string>TLSv1.1</string>
</dict>
</dict>
</dict>
If you intent to use this method in a commercial App or don't want to hit the usage limit of the underlying API, you can use your Pro key like this:
// Before using the API, e.g. in AppDelegate
Location.ipAPIKey = "{YOUR-KEY-HERE}"
You can get data about current device's heading using observeHeading() function.
Location.getHeading(HeadingFrequency.Continuous(interval: 5), accuracy: 1.5, allowsCalibration: true, didUpdate: { newHeading in
// each changes of at least 1.5 degree and 5 seconds after the last measurement is reported here
}) { error in
// something bad occurred
}
- SwiftLocation works even in background; just use
Location.allowsBackgroundEvents = true
(don't forget to define UIBackgroundModes array). - SwiftLocation can optimize power usage by reducing location updates via
Location.pausesLocationUpdatesWhenPossible = true
- SwiftLocation can defer location updates: use it to optimize power usage when you want location data with GPS accuracy but do not need to process that data right away; you can get the complete location points after certain time or distance (use
Location..stopDeferredLocationUpdates()
to stop deferred updates) - Shortcuts to pause or resume requests:
Location.startAllLocationRequests()
(start pending requests),Location.stopAllLocationRequests
(pause or stop all requests),Location.stopSignificantLocationRequests()
(pause or stop only significant requests) - Use
Location.minimumDistance = ...
to define the minimum distance (measured in meters) a device must move horizontally before an update event is generated (by default is ignored, all events are generated)
You can do a reverse geocoding from a given pair of coordinates or a readable address string. You can use both Google or Apple's services to perform these request.
Swift location provides three different methods:
reverse(address:using:onSuccess:onError)
: allows you to get aCLPlacemark
object from a source address string. It requireservice
(.Apple
or.Google
) and anaddress
string.reverse(coordinates:using:onSuccess:onError:)
: allows you to get aCLPlacemark
object from a source coordinates expressed asCLLocationCoordinate2D
.reverse(location:using:onSuccess:onError:)
the same of the previous method but accept aCLLocation
as source object.
Some examples:
let addString = "1 Infinite Loop, Cupertino"
Location.reverse(address: addString, onSuccess: { foundPlacemark in
// foundPlacemark is a CLPlacemark object
}) { error in
// failed to reverse geocoding due to an error
}
let coordinates = CLLocationCoordinate2DMake(41.890198, 12.492204)
Location.reverse(coordinates: coordinates, onSuccess: { foundPlacemark in
// foundPlacemark is a CLPlacemark object
}) { error in
// failed to reverse geocoding due to an error
}
CoreLocation
allows you to get notified when user visits an interesting place by returning a CLVisit
object: it encapsulates information about interesting places that the user has been. Visit objects are created by the system. The visit includes the location where the visit occurred and information about the arrival and departure times as relevant. You do not create visit objects directly, nor should you subclass CLVisit
.
You can add a new handler to get notification about visits via getInterestingPlaces(onDidVisit:)
function.
Location.getInterestingPlaces { newVisit in
// a new CLVisit object is returned
}
You can easily to be notified when the user crosses a region based boundary. You use region monitoring to detect boundary crossings of the specified region and you use those boundary crossings to perform related tasks. For example, upon approaching a dry cleaners, an app could notify the user to pick up any clothes that had been dropped off and are now ready.
SwiftLocation offers to you a simple method called monitor()
to get notified about these kind of events:
// Define a geographic circle region
let centerPoint = CLLocationCoordinate2DMake(0, 0)
let radius = CLLocationDistance(100)
do {
// Attempt to monitor the region
let request = try Beacons.monitor(geographicRegion: centerPoint, radius: radius, onStateDidChange: { newState in
// newState is .Entered if user entered into the region defined by the center point and the radius or .Exited if it move away from the region.
}) { error in
// something bad has happened
}
} catch let err {
// Failed to initialize region (bad region, monitor is not supported by the hardware etc.)
print("Cannot monitor region due to an error: \(err)")
}
Usually you can pause()
/start()
or cancel()
the request itself; just keep a reference to it.
You can easily to be notified when the user crosses a region defined by a beacon or get notified when users did found one or more beacons nearby.
Just use monitor()
function:
let b_proximity = "00194D5B-0A08-4697-B81C-C9BDE117412E"
// You can omit major and minor to get notified about the entire beacon family defined by b_proximity
let b_major = CLBeaconMajorValue(64224)
let b_minor = CLBeaconMinorValue(43514)
do {
// Just create a Beacon structure which represent our beacon
let beacon = Beacon(proximity: proximity, major: major, minor: minor)
// Attempt to monitor beacon
try Beacons.monitor(beacon: beacon, events: Event.RegionBoundary, onStateDidChange: { state in
// events called when user crosses the boundary the region defined by passed beacon
}, onRangingBeacons: { visibleBeacons in
// events is fired countinously to get the list of visible beacons (with observed beacon) nearby
}, onError: { error in
// something went wrong. request is cancelled.
})
} catch let err {
// failed to monitor beacon
}
You can set your device to act like a beacon (this feature works only in foreground due to some limitations of Apple's own methods).
Keep in mind: advertising not works in background.
let request = Beacons.advertise(beaconName: "name", UUID: proximity, major: major, minor: minor, powerRSSI: 4, serviceUUIDs: [])
Use stop()
on request
to stop beacon advertise.
var request = Location.getLocation(withAccuracy: .City, frequency: .Continuous, timeout: nil, onSuccess: { (loc) in
// location update
}) { (last, err) in
// error
}
request.onAuthorizationDidChange = { newStatus in
print("New status \(newStatus)")
}
- Request's cancel() function now has error as optional argument
- This is the last Swift 2.2 version
- Added support for ip-api Pro API Key
- Added documentation reference for ip-api limit usage, pro version and app transport security on iOS 9 or later.
- Each
Request
implement.onAuthorizationDidChange()
so you can observe for CLLocationManager auth events.
- FIX #61 Fixed several issues with location services
start()
func.
- FIX #60 A new rewritten Beacon Monitoring service class
- Added support for deferred location updates
- Better handle not supported hardware errors
- Fixed an issue which does not reset or start unwanted timeout timer in location services
- Better support to
pause(),start()
andcancel()
requests
- FIX #48 Fixed an issue which blocks the library to report correct values for
.Room
and.Navigation
accuracy levels - FIX #55 Fixed an issue with timeout timer of location manager which is called even when the location was found correctly.
- [NEW]
CLLocationAuthorizationStatus
is now conform to CustomStringConvertible protocol.
- First stable version
This library require iOS 8+ and Swift 2.2.
CocoaPods is a dependency manager for Cocoa projects. You can install it with the following command:
$ gem install cocoapods
CocoaPods 0.39.0+ is required to build SwiftLocation 1.0.0+. To integrate SwiftLocation into your Xcode project using CocoaPods, specify it in your Podfile:
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '9.0'
use_frameworks!
target '<Your Target Name>' do
pod 'SwiftLocation', '~> 1.0.5'
end
Swift Versions:
- Swift 2.2
pod 'SwiftLocation', '1.0.5'
- Swift 3
pod 'SwiftLocation', '>= 1.0.6'
- Swift 2.3
pod 'SwiftLocation', :git => 'https://github.com/malcommac/SwiftLocation.git', :branch => 'feature/swift2.3'
Then, run the following command:
$ pod install
Carthage is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.
You can install Carthage with Homebrew using the following command:
$ brew update
$ brew install carthage
To integrate SwiftLocation into your Xcode project using Carthage, specify it in your Cartfile:
github "malcommac/SwiftLocation" ~> 1.0
Run carthage update
to build the framework and drag the built SwiftLocation.framework
into your Xcode project.
SwiftLocation was created and mantained by Daniele Margutti.
- Email: hello@danielemargutti.com
- Website: danielemargutti.com
- Twitter: @danielemargutti
While SwiftLocation is free to use and change (I'm happy to discuss any PR with you) if you plan to use it in your project please consider to add:
"Location Services provided by SwiftLocation by Daniele Margutti"
and a link to this GitHub page.
Drop me an email so I'll add your creation here!
SwiftLocation is available under the MIT license.
See the LICENSE file for more info.