iOS
This tutorial will walk you through the steps of using the Ride Request Widget in your iOS app. We will set up and configure the SDK, then walk through a quick integration and an advanced integration.
¶ Your iOS Project
We can create a new Single View Application project to demonstrate how to begin using the SDK. In XCode, choose File > New > Project and when prompted to “Choose a template for your new project”, select Single View Application and click Next.
In the next screen, set the Product Name field to any name you want, leave everything else as the default and click Next. Choose which folder you want to save the project to and click Create. You now have a boilerplate app with just one view!
¶ Add the SDK to your project
There are currently two ways to add the Uber Rides iOS SDK to your project:
Using a dependency manager such as Carthage or CocoaPods makes it easy to keep your app updated with the latest version of the SDK.
¶ CocoaPods
The Uber Rides iOS SDK is a CocoaPod written in Swift. You can install CocoaPods with the following command:
$ gem install cocoapods
To integrate Uber Rides into your Xcode project, navigate to the directory that contains your project and create a new Podfile with pod init
. Add the following under your Podfile’s target:
target 'Your Project Name' do
use_frameworks!
pod 'UberRides', '~> 0.9'
end
Then, run the following command to install the dependency:
$ pod install
Next, close your Xcode project. In your project folder, you should see another file alongside your .xcodeproj
file: the .xcworkspace
file. Open the .xcworkspace
file.
Congratulations, you’ve added the Uber Rides iOS SDK into your project using CocoaPods! Next, you have to configure the sdk.
¶ Carthage
You can integrate Uber Rides into your project using Carthage. You can install Carthage (with XCode 7+) via homebrew:
brew update
brew install carthage
To install UberRides via Carthage, you need to create a Cartfile
. In the root directory of your project, run the following command:
touch Cartfile
In the editor of your choice open the file and add the following:
# UberRides
github "uber/rides-ios-sdk" ~> 0.9
Now run the following command to checkout & build our repo and dependencies.
carthage update --platform iOS
You should now have a Carthage/Build
folder in your project directory. Open your .xcodeproj
and go to the General settings tab. In the Linked Frameworks and Libraries section, drag and drop each framework (in Carthage/Build/iOS
)
Now, open your application target’s Build Phases settings tab, click the +
icon, and select New Run Script Phase. Add the following to the script area:
/usr/local/bin/carthage copy-frameworks
and add the paths to the required frameworks in Input Files
$(SRCROOT)/Carthage/Build/iOS/UberRides.framework
Congratulations, you’ve added the Uber Rides iOS SDK into your project using Carthage! Next, you have to configure the sdk.
¶ Configuring the SDK
To begin making calls to the Uber API, you need to register an application on the Uber Developer Site and get credentials for your app.
Then, configure your Xcode with information for the Uber SDK. Locate the Info.plist file for your application. Right-click this file and select Open As > Source Code
Add the following code snippet, replacing the placeholders within the square brackets ([]
) with your app’s information from the developer dashboard. (Note: Do not include the square brackets)
<key>UberClientID</key>
<string>[ClientID]</string>
<key>UberDisplayName</key>
<string>[App Name]</string>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>uber</string>
<string>uberauth</string>
</array>
¶ Location Services
Getting the user to authorize location services can be done with Apple’s CoreLocation framework. The Uber Rides SDK checks the value of locationServicesEnabled()
in CLLocationManager
, which must be true to be able to retrieve the user’s current location.
Also, for iOS 9, don’t forget to add a usage description key into your app’s Info.plist
<key>NSLocationWhenInUseUsageDescription</key>
<string>[Reason you want the location]</string>
¶ Quick Integration
The Uber Rides SDK provides a simple way to add the Ride Request Widget in only a few lines of code via the RideRequestButton
. You simply need to provide a RideRequesting
object and an optional RideParameters
object.
// Pass in a UIViewController to modally present the Ride Request Widget over
let behavior = RideRequestViewRequestingBehavior(presentingViewController: self)
// Optional, defaults to using the user’s current location for pickup
let location = CLLocation(latitude: 37.787654, longitude: -122.402760)
let parameters = RideParametersBuilder().setPickupLocation(location).build()
let button = RideRequestButton(rideParameters: parameters, requestingBehavior: behavior)
self.view.addSubview(button)
That’s it! When a user taps the button, a RideRequestViewController
will be modally presented, containing a RideRequestView
prefilled with the information provided from the RideParameters
object. If they aren’t signed in, the modal will display a login page and automatically continue to the Ride Request Widget once they sign in.
Basic error handling is provided by default, but can be overwritten by specifying a RideRequestViewControllerDelegate
.
extension <your_class> : RideRequestViewControllerDelegate {
func rideRequestViewController(rideRequestViewController: RideRequestViewController, didReceiveError error: NSError) {
let errorType = RideRequestViewErrorType(rawValue: error.code) ?? .Unknown
// Handle error here
switch errorType {
case .AccessTokenMissing:
// No AccessToken saved
case .AccessTokenExpired:
// AccessToken expired / invalid
case .NetworkError:
// A network connectivity error
case .Unknown:
// Other error
}
}
}
// Use your_class as the delegate
let behavior = RideRequestViewRequestingBehavior(self)
let delegate = your_class()
behavior.modalRideRequestViewController.rideRequestViewController.delegate = delegate
// Create the button same as before
let button = RideRequestButton(rideParameters: parameters, requestingBehavior: behavior)
¶ Advanced Integration
If you want to provide a more custom experience in your app, there are a few classes to familiarize yourself with. Read the sections below and you’ll be requesting rides in no time!
¶ Implicit Grant Authorization
Before you can request any rides, you need to get an AccessToken
. The Uber Rides SDK provides the LoginManager
class for this task. Simply instantiate an instance use its login method to present the login screen to the user.
let loginManager = LoginManager()
loginManager.login(requestedScopes:[.RideWidgets], presentingViewController: self, completion: { accessToken, error in
// Completion block. If accessToken is non-nil, you’re good to go
})
The only required scope for the control is the RideWidgets
scope, but you can pass in any other scopes that you’d like access to.
The SDK presents a web view controller where the user logs into their Uber account, or creates an account, and authorizes the requested scopes, retrieving an access token which is automatically saved to the keychain. Once the SDK has the access token, the ride request widget is ready to be used!
¶ Custom Authorization / TokenManager
If your app allows users to authorize via your own customized logic, you will need to create an AccessToken
manually and save it in the keychain using the TokenManager
.
let accessTokenString = "access_token_string"
let token = AccessToken(tokenString: accessTokenString)
if TokenManager.saveToken(token) {
// Success
} else {
// Unable to save
}
The TokenManager
can also be used to fetch and delete AccessTokens
TokenManger.fetchToken()
TokenManager.deleteToken()
¶ RideParameters
The SDK provides an simple object for defining your ride requests. The RideParameters
object lets you specify pickup location, dropoff location, product ID, and more. Creating RideParameters
is easy using the RideParametersBuilder
object.
let builder = RideParametersBuilder()
let pickupLocation = CLLocation(latitude: 37.787654, longitude: -122.402760)
let dropoffLocation = CLLocation(latitude: 37.775200, longitude: -122.417587)
//You can chain builder function calls
builder.setPickupLocation(pickupLocation).setDropoffLocation(dropoffLocation)
let rideParameters = builder.build()
You can also have the SDK determine the user’s current location (you must handle getting location permission beforehand, however)
let builder = RideParametersBuilder()
builder.setPickupToCurrentLocation()
let parameters = builder.build()
// A RideParameters object does this by default
let parameters = RideParametersBuilder().build() //equivalent
¶ RideRequestView
The RideRequestView
is like any other view you’d add to your app. Create a new instance using a RideParameters
object and add it to your app wherever you like.
// Example of setting up the RideRequestView
let location = CLLocation(latitude: 37.787654, longitude: -122.402760)
let parameters = RideParametersBuilder().setPickupLocation(location).build()
let rideRequestView = RideRequestView(rideParameters: parameters, frame: self.view.bounds)
self.view.addSubview(rideRequestView)
That’s it! When you’re ready to show the control, call the load()
function.
You can also optionally specify a RideRequestViewDelegate
to handle errors loading the widget.
extension <your_class> : RideRequestViewDelegate {
func rideRequestView(rideRequestView: RideRequestView, didReceiveError error: NSError) {
let errorType = RideRequestViewErrorType(rawValue: error.code) ?? .Unknown
// Handle error here
switch errorType {
case .AccessTokenMissing:
// No AccessToken saved
case .AccessTokenExpired:
// AccessToken expired / invalid
case .NetworkError:
// A network connectivity error
case .Unknown:
// Other error
}
}
}
¶ RideRequestViewController
A RideRequestViewController
is simply a UIViewController
that contains a fullscreen RideRequestView
. It also handles logging in non-authenticated users for you. Create a new instance with your desired RideParameters
and LoginManager
(used to log in, if necessary).
// Setting up a RideRequestViewController
let parameters = RideParametersBuilder().build()
let loginManager = LoginManager()
let rideRequestViewController = RideRequestViewController(rideParameters: parameters, loginManager: loginManager)
You can also optionally specify a RideRequestViewControllerDelegate
to handle potential errors passed from the wrapped RideRequestView
extension <your_class> : RideRequestViewControllerDelegate {
func rideRequestViewController(rideRequestViewController: RideRequestViewController, didReceiveError error: NSError) {
let errorType = RideRequestViewErrorType(rawValue: error.code) ?? .Unknown
// Handle error here
switch errorType {
case .AccessTokenMissing:
// No AccessToken saved
case .AccessTokenExpired:
// AccessToken expired / invalid
case .NetworkError:
// A network connectivity error
case .Unknown:
// Other error
}
}
}
¶ Where to go from here
Now that your users are able to request rides using the widget you can work on a deeper integration using our API.