Configure Your Twitter App
Note
The Fabric Mac app will automatically create and configure a Twitter application when you use it to integrate the Twitter Kit into your app. If you would like to use keys from an existing Twitter app in your app read on, otherwise you may happily ignore this document.
You will need a consumer key and a consumer secret (collectively, a “Twitter app”) to use Twitter kits and access Twitter’s API. You can create or review an application’s settings at Twitter’s developer site
- Go to your Twitter application’s settings at Twitter’s developer site.
- Find your application and go to the permissions tab.
- Select the appropriate permissions for your needs (e.g. “Read and write”)
- If you are using login, add a placeholder URL in the Callback URL field (eg. “http://example.com”).
- Click update settings.
Callback URL
Although Fabric will ignore the value of the callback URL, it must be set to a valid URL for the app to work with the SDK.
Allow Sign in with Twitter
If you wish to use Login with Twitter, be sure that Allow this application to be used to Sign in to Twitter is checked:
Additional Permissions
If your app requires writing Tweets or accessing DM’s you will need to enable additional permissions for your app.
Changes to the application permission model will only take effect in access tokens obtained after the permission model change is saved. You will need to re-negotiate existing access tokens to alter the permission level associated with each of your application’s users.
![](https://g.twimg.com/dev/sites/default/files/images_documentation/app-permissions.png)
Integrate With Your App
To initialize the Twitter Kit with your app’s credentials, pass them to startWithConsumerKey:consumerSecret:
before passing the shared instance to Fabric.
Calling startWithConsumerKey:consumerSecret:
will override any keys which were automatically configured. Automatically configured keys live in your app’s Info.plist under the key Fabric
.
// Objective-C
[[Twitter sharedInstance] startWithConsumerKey:@
"your_key"
consumerSecret:@
"your_secret"
];
[Fabric with:@[[Twitter sharedInstance]]];
// Swift
Twitter.sharedInstance().startWithConsumerKey(
"your_key"
,
consumerSecret:
"your_secret"
)
Fabric.with([Twitter.sharedInstance()])
|
Log in with Twitter
User Authentication
The Log in with Twitter feature enables app users to authenticate with Twitter.
Note
If you’re not using Fabric’s auto-generated Twitter credentials, ensure that “Allow this application to be used to Sign in to Twitter” is checked for your Twitter app before using this feature.
The SDK first attempts to leverage system Twitter accounts, via Accounts.framework. If that fails, it falls back to presenting an OAuth flow. After successful authentication, the SDK automatically saves the account to iOS system accounts and the TWTRSession
will contain a token, secret, username, and user ID of the user. If authentication fails, the error will be non-nil.
User authentication is required for API requests that require a user context, for example: Tweeting or following other users.
Log in Button
The simplest way to authenticate a user is using TWTRLogInButton
:
// Objective-C
TWTRLogInButton* logInButton = [TWTRLogInButton
buttonWithLogInCompletion:
^(TWTRSession* session,
NSError
* error) {
if
(session) {
NSLog
(@
"signed in as %@"
, [session userName]);
}
else
{
NSLog
(@
"error: %@"
, [error localizedDescription]);
}
}];
logInButton.center =
self
.view.center;
[
self
.view addSubview:logInButton];
|
// Swift
let logInButton = TWTRLogInButton(logInCompletion:
{ (session, error) in
if
(session !=
nil
) {
println(
"signed in as \(session.userName)"
);
}
else
{
println(
"error: \(error.localizedDescription)"
);
}
})
logInButton.center =
self
.view.center
self
.view.addSubview(logInButton)
|
This will render a button that looks like:
Log in Method
// Objective-C
[[Twitter sharedInstance] logInWithCompletion:^
(TWTRSession *session,
NSError
*error) {
if
(session) {
NSLog
(@
"signed in as %@"
, [session userName]);
}
else
{
NSLog
(@
"error: %@"
, [error localizedDescription]);
}
}];
|
// Swift
Twitter.sharedInstance().logInWithCompletion {
(session, error) -> Void in
if
(session !=
nil
) {
println(
"signed in as \(session.userName)"
);
}
else
{
println(
"error: \(error.localizedDescription)"
);
}
}
|
Guest Authentication
To use the SDK without requiring user authentication first, you will need to log in as a guest. Guest authentication is limited to API requests that do not require a user context. This means, for example, that you cannot Tweet with guest authentication. You can get a user’s timeline of public Tweets.
Guest authentication is an extension to application authentication and as such, the permission scope and rate limits are the same as application authentication. There are however two major differences:
- rate limits will scale with the number of users of your application
- guest auth tokens have a time expiration
To obtain a guest token for your user, you can call the following method:
// Objective-C
[[Twitter sharedInstance] logInGuestWithCompletion:^(TWTRGuestSession *guestSession,
NSError
*error) {
if
(guestSession) {
// make API calls that do not require user auth
}
else
{
NSLog
(@
"error: %@"
, [error localizedDescription]);
}
}];
|
// Swift
Twitter.sharedInstance().logInGuestWithCompletion { guestSession, error in
if
(guestSession !=
nil
) {
// make API calls that do not require user auth
}
else
{
println(
"error: \(error.localizedDescription)"
);
}
}
|
We will automatically retry once on token expiration in TwitterKit. Additionally, here is a sample snippet you can use to detect a timeout and trigger a retry manually.
// Objective-C
[[[Twitter sharedInstance] APIClient] loadTweetWithID:@
"20"
completion:^(TWTRTweet *tweet,
NSError
*error) {
if
(error.domain == TWTRAPIErrorDomain && (error.code == TWTRAPIErrorCodeInvalidOrExpiredToken || error.code == TWTRAPIErrorCodeBadGuestToken)) {
// can manually retry by calling -[Twitter logInGuestWithCompletion:]
}
}];
|
// Swift
Twitter.sharedInstance().APIClient.loadTweetWithID(
"20"
) { tweet, error in
if
error.domain == TWTRAPIErrorDomain && (error.code == .InvalidOrExpiredToken || error.code == .BadGuestToken) {
// can manually retry by calling Twitter.sharedInstance().logInGuestWithCompletion
}
}
|
Request a User's Email Address
Requesting a user’s email address requires your application to be whitelisted by Twitter. To request access, please use this form.
The TWTRShareEmailViewController
class presents a view to the user to request access to the email address associated with their Twitter account. It must be presented modally.
![](https://g.twimg.com/dev/documentation/image/share_email.png)
Presenting the Share Email Dialog
To present the share email dialog, initialize an instance of TWTRShareEmailViewController
and pass a completion block. The completion block will pass either an email address or an error when the user has granted or denied permission to access their email address.
Note
You should first check whether the user is signed in to Twitter prior to presenting the dialog. You will receive an error (TWTRErrorDomain, TWTRErrorCodeNoAuthentication), via the completion block, if the user is not signed in.
If the user grants access and the email address is available, the completion block will contain the email address.
Note
Even if the user grants access to her email address, it is not guaranteed you will get an email address. For example, if someone signed up for Twitter with a phone number instead of an email address, the email field may be empty. When this happens, the completion block will pass an error because there is no email address available.
If the user denies access, you will receive an error (TWTRErrorDomain, TWTRErrorCodeUserDeclinedPermission
), via the completion block.
Attempting to use TWTRShareEmailViewController
without first having your app whitelisted will yield an error (TWTRAPIErrorDomain, TWTRAPIErrorCodeNotAuthorizedForEndpoint
) when the request to Twitter fails. Attempting to use TWTRShareEmailViewController
with tokens generated before whitelisting your application will yield the same error.
Here’s an example that shows how to use TWTRShareEmailViewController
:
if
([[Twitter sharedInstance] session]) {
TWTRShareEmailViewController* shareEmailViewController =
[[TWTRShareEmailViewController alloc]
initWithCompletion:^(
NSString
* email,
NSError
* error) {
NSLog
(@
"Email %@, Error: %@"
, email, error);
}];
[
self
presentViewController:shareEmailViewController
animated:
YES
completion:
nil
];
}
else
{
// TODO: Handle user not signed in (e.g.
// attempt to log in or show an alert)
}
|
Note
TWTRShareEmailViewController will dismiss itself once the user has granted or denied permission to share their email address. You do not need to call dismissViewControllerAnimated:completion:.
Note
The completion block passed at initialization time is required.
Access Twitter's REST API
The REST API can be used to make authenticated Twitter API requests. Though it can be accessed manually, we recommend using the convenience methods whenever possible.
Use the Provided Convenience Methods
Note
You must have previously completed the login flow for the user in order for this method to work.
Load a Single Tweet
Load a single tweet to show in a Regular style tweet:
// Objective-C
// Fetches @jack's first Tweet
[[[Twitter sharedInstance] APIClient] loadTweetWithID:@
"20"
completion:^(TWTRTweet *tweet,
NSError
*error) {
// handle the response or error
}];
|
// Swift
// Fetches @jack's first Tweet
Twitter.sharedInstance().APIClient.loadTweetWithID(
"20"
) {
(tweet, error) -> Void in
// handle the response or error
}
|
Load Multiple Tweets
// Objective-C
NSArray
*tweetIDs = @[@
"20"
, @
"510908133917487104"
];
[[[Twitter sharedInstance] APIClient]
loadTweetsWithIDs:tweetIDs
completion:^(
NSArray
*tweets,
NSError
*error) {
// handle the response or error
}];
|
// Swift
let tweetIDs = [
"20"
,
"510908133917487104"
]
Twitter.sharedInstance().APIClient
.loadTweetsWithIDs(tweetIDs) {
(tweets, error) -> Void in
// handle the response or error
}
|
Load a User
If you are looking to load a single user:
// Objective-C
[[[Twitter sharedInstance] APIClient] loadUserWithID:@
"12"
completion:^(TWTRUser *user,
NSError
*error)
{
// handle the response or error
}];
|
// Swift
Twitter.sharedInstance().APIClient.loadUserWithID(
"12"
) {
(user, error) -> Void in
// handle the response or error
}
|
Constructing a Twitter Request Manually
If you want to to access other Twitter API endpoints, you may choose to construct a request manually. For example, you might do something like this:
// Objective-C
NSString
*statusesShowEndpoint = @
"https://api.twitter.com/1.1/statuses/show.json"
;
NSDictionary
*params = @{@
"id"
: @
"20"
};
NSError
*clientError;
NSURLRequest
*request = [[[Twitter sharedInstance] APIClient]
URLRequestWithMethod:@
"GET"
URL:statusesShowEndpoint
parameters:params
error:&clientError];
if
(request) {
[[[Twitter sharedInstance] APIClient]
sendTwitterRequest:request
completion:^(
NSURLResponse
*response,
NSData
*data,
NSError
*connectionError) {
if
(data) {
// handle the response data e.g.
NSError
*jsonError;
NSDictionary
*json = [
NSJSONSerialization
JSONObjectWithData:data
options:0
error:&jsonError];
}
else
{
NSLog
(@
"Error: %@"
, connectionError);
}
}];
}
else
{
NSLog
(@
"Error: %@"
, clientError);
}
|
// Swift
let statusesShowEndpoint =
"https://api.twitter.com/1.1/statuses/show.json"
let params = [
"id"
:
"20"
]
var clientError :
NSError
?
let request = Twitter.sharedInstance().APIClient.
URLRequestWithMethod(
"GET"
, URL: statusesShowEndpoint, parameters: params,
error: &clientError)
if
request !=
nil
{
Twitter.sharedInstance().APIClient.
sendTwitterRequest(request) {
(response, data, connectionError) -> Void in
if
(connectionError ==
nil
) {
var jsonError :
NSError
?
let json : AnyObject? =
NSJSONSerialization
.JSONObjectWithData(data,
options:
nil
,
error: &jsonError)
}
else
{
println(
"Error: \(connectionError)"
)
}
}
}
else
{
println(
"Error: \(clientError)"
)
}
|
Use OAuth Echo
OAuth Echo is a means to securely delegate OAuth authorization with a third party while interacting with an API.
For example, you may wish to verify a user’s credentials from your app’s server (the third party) rather than your app.
More technical information about OAuth Echo can be found here.
Instantiating TWTROAuthSigning
TWTROAuthSigning
relies on the application auth config as well as a user session, either from Digits or from Twitter.
The TWTRAuthConfig
object encapsulates the credentials to identify your Twitter or Digits application. You can get this object from the Twitter class (see code examples below).
An TWTRAuthConfig
object represents the user credentials of a Twitter of Digits user session. Both the TWTRSession
and the DGTSession
classes conform to this protocol.
// Objective-C
// Instantiates TWTROAuthSigning
TWTROAuthSigning *oauthSigning =
[[TWTROAuthSigning alloc]
initWithAuthConfig:
[Twitter sharedInstance].authConfig
authSession:[Twitter sharedInstance].session];
|
// Swift
// Instantiates TWTROAuthSigning
let oauthSigning = TWTROAuthSigning(
authConfig: Twitter.sharedInstance().authConfig,
authSession: Twitter.sharedInstance().session())
|
Creating OAuth Echo signing headers
The easiest way to use OAuth Echo is by requesting the authorization headers to make a request to verify_credentials from outside the app.
// Objective-C
NSDictionary
*authHeaders =
[oauthSigning OAuthEchoHeadersToVerifyCredentials];
|
// Swift
let authHeaders = oauthSigning
.OAuthEchoHeadersToVerifyCredentials()
|
The authHeaders
dictionary contains the X-Auth-Service-Provider
(defined in the TWTROAuthEchoRequestURLStringKey
constant) and X-Verify-Credentials-Authorization
(defined in the TWTROAuthEchoAuthorizationHeaderKey
constant) keys. Your backend should take the OAuth signature in X-Verify-Credentials-Authorization
, and use it to set the Authorization
header for a request to the URL in X-Auth-Service-Provider
.
// Objective-C
NSMutableURLRequest
*request =
[
NSMutableURLRequest
requestWithURL:
[
NSURL
URLWithString:
@
"http://api.yourbackend.com/check_credentials"
]];
request.allHTTPHeaderFields = authHeaders;
|
// Swift
let request =
NSMutableURLRequest
(
URL:
NSURL
(string:
"http://api.yourbackend.com/check_credentials"
))
request.allHTTPHeaderFields = authHeaders
|
Show Tweets
Note
Tweets can be rendered using user authentication or guest authentication. See Log in with Twitter.
Display a Single Tweet
To show a single Tweet, you first need to load that Tweet from the network (seeAccess Twitter’s REST API) and then create and configure a view with that Tweet model object. Then it may be added to the view hierarchy. If you would like to render Tweets in a UITableView
, please see the Show a UITableView
of Tweets.
If you have stored Twitter API responses you can also construct Tweet model objects from static JSON (see Using Static JSON for Tweets, below).
1. Import the Twitter kit framework
// Swift
import TwitterKit
|
// Objective-C
#import <TwitterKit/TwitterKit.h>
|
2. Load Tweets from the network, then create TWTRTweetView
in completion block
// Swift
Twitter.sharedInstance().logInGuestWithCompletion { session, error in
if
let validSession = session {
Twitter.sharedInstance().APIClient.loadTweetWithID(
"20"
) { tweet, error in
if
let t = tweet {
self
.tweetView.configureWithTweet(t)
}
else
{
println(
"Failed to load Tweet: \(error.localizedDescription)"
)
}
}
}
else
{
println(
"Unable to login as guest: \(error.localizedDescription)"
)
}
}
|
// Objective-C
__weak typeof(
self
) weakSelf =
self
;
[TwitterKit logInGuestWithCompletion:^(TWTRGuestSession *guestSession,
NSError
*error) {
if
(session) {
// Loading public Tweets do not require user auth
[[[Twitter sharedInstance] APIClient] loadTweetWithID:@
"20"
completion:^(TWTRTweet *tweet,
NSError
*error) {
if
(tweet) {
[weakSelf.tweetView configureWithTweet:tweet]
}
else
{
NSLog
(@
"Failed to load tweet: %@"
, [error localizedDescription]);
}
}];
}
else
{
NSLog
(@
"Unable to log in as guest: %@"
, [error localizedDescription]);
}
}];
|
Tweet View Style
There are two different styles for Tweet views: TWTRTweetViewStyleRegular
and TWTRTweetViewStyleCompact
. Regular Tweet views show large images and have a “Share Tweet” button, whereas compact Tweet views are designed to be put inside tableviews through the TWTRTweetTableViewCell
(see Show a UITableView of Tweets
).
![](https://g.twimg.com/dev/documentation/image/show_tweet_regular.png)
![](https://g.twimg.com/dev/documentation/image/show_tweet_compact.png)
Configuring Tweet View Colors & Themes
To change the colors of a Tweet view you have two options:
1. Set the theme property of the TWTRTweetView.
// Objective-C
// Set the theme directly
tweetView.theme = TWTRTweetViewThemeDark;
// Use custom colors
tweetView.primaryTextColor = [UIColor yellowColor];
tweetView.backgroundColor = [UIColor blueColor];
|
// Swift
// Set the theme directly
tweetView.theme = .Dark
// Use custom colors
tweetView.primaryTextColor = UIColor.yellowColor()
tweetView.backgroundColor = UIColor.blueColor()
|
2. Set visual properties using the UIAppearanceProxy for TWTRTweetView.
// Objective-C
// Set all future tweet views to use dark theme using UIAppearanceProxy
[TWTRTweetView appearance].theme = TWTRTweetViewThemeDark;
// Use custom colors
[TWTRTweetView appearance].primaryTextColor = [UIColor yellowColor];
[TWTRTweetView appearance].backgroundColor = [UIColor blueColor];
[TWTRTweetView appearance].linkTextColor = [UIColor redColor];
|
// Swift
// Set all future tweet views to use dark theme using UIAppearanceProxy
TWTRTweetView.appearance().theme = .Dark
// Use custom colors
TWTRTweetView.appearance().primaryTextColor = UIColor.yellowColor()
TWTRTweetView.appearance().backgroundColor = UIColor.blueColor()
TWTRTweetView.appearance().linkTextColor = UIColor.redColor()
|
Show a UITableView of Tweets
TWTRTweetTableViewCell
may be used to display Tweet views in a table view.
// Objective-C
// TweetTableViewDemoViewController.m
#import <TwitterKit/TwitterKit.h>
#import "TweetTableViewDemoViewController.h"
static
NSString
*
const
TweetTableReuseIdentifier = @
"TweetCell"
;
@interface
TweetTableViewDemoViewController () <TWTRTweetViewDelegate>
@property
(
nonatomic
, strong)
NSArray
*tweets;
// Hold all the loaded tweets
@end
@implementation
TweetTableViewDemoViewController
- (
void
)viewDidLoad {
[
super
viewDidLoad];
NSArray
*tweetIDs = @[@
"20"
,
// @jack's first Tweet
@
"510908133917487104"
// our favorite Bike tweet
];
// Setup tableview
self
.tableView.estimatedRowHeight = 150;
self
.tableView.rowHeight = UITableViewAutomaticDimension;
// Explicitly set on iOS 8 if using automatic row height calculation
self
.tableView.allowsSelection =
NO
;
[
self
.tableView registerClass:[TWTRTweetTableViewCell
class
] forCellReuseIdentifier:TweetTableReuseIdentifier];
// Load tweets
__weak typeof(
self
) weakSelf =
self
;
[[[Twitter sharedInstance] APIClient] loadTweetsWithIDs:tweetIDs completion:^(
NSArray
*tweets,
NSError
*error) {
if
(tweets) {
typeof(
self
) strongSelf = weakSelf;
strongSelf.tweets = tweets;
[strongSelf.tableView reloadData];
}
else
{
NSLog
(@
"Failed to load tweet: %@"
, [error localizedDescription]);
}
}];
}
# pragma mark - UITableViewDelegate Methods
- (
NSInteger
)tableView:(UITableView *)tableView numberOfRowsInSection:(
NSInteger
)section {
return
[
self
.tweets count];
}
- (TWTRTweetTableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(
NSIndexPath
*)indexPath {
TWTRTweet *tweet =
self
.tweets[indexPath.row];
TWTRTweetTableViewCell *cell = (TWTRTweetTableViewCell *)[tableView dequeueReusableCellWithReuseIdentifier:TweetTableReuseIdentifier forIndexPath:indexPath];
[cell configureWithTweet:tweet];
cell.tweetView.delegate =
self
;
return
cell;
}
// Calculate the height of each row
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(
NSIndexPath
*)indexPath {
TWTRTweet *tweet =
self
.tweets[indexPath.row];
return
[TWTRTweetTableViewCell heightForTweet:tweet width:CGRectGetWidth(
self
.view.bounds)];
}
@end
|
// Swift
import TwitterKit
class
TweetTableViewDemoViewController: UITableViewController, TWTRTweetViewDelegate {
let tweetTableReuseIdentifier =
"TweetCell"
// Hold all the loaded Tweets
var tweets: [TWTRTweet] = [] {
didSet {
tableView.reloadData()
}
}
let tweetIDs = [
"20"
,
// @jack's first Tweet
"510908133917487104"
]
// our favorite bike Tweet
override func viewDidLoad() {
// Setup the table view
tableView.estimatedRowHeight = 150
tableView.rowHeight = UITableViewAutomaticDimension
// Explicitly set on iOS 8 if using automatic row height calculation
tableView.allowsSelection =
false
tableView.registerClass(TWTRTweetTableViewCell.
self
, forCellReuseIdentifier: tweetTableReuseIdentifier)
// Load Tweets
Twitter.sharedInstance().APIClient.loadTweetsWithIDs(tweetIDs) { tweets, error in
if
let ts = tweets as [TWTRTweet] {
self
.tweets = ts
}
else
{
println(
"Failed to load tweets: \(error.localizedDescription)"
)
}
}
}
// MARK: UITableViewDelegate Methods
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return
self
.tweets.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath:
NSIndexPath
) -> UITableViewCell {
let tweet = tweets[indexPath.row]
let cell = tableView.dequeueReusableCellWithIdentifier(tweetTableReuseIdentifier, forIndexPath: indexPath) as TWTRTweetTableViewCell
cell.tweetView.delegate =
self
return
cell
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath:
NSIndexPath
) -> CGFloat {
let tweet = tweets[indexPath.row]
return
TWTRTweetTableViewCell.heightForTweet(tweet, width: CGRectGetWidth(
self
.view.bounds))
}
}
|
Delegate Methods
You may respond to user actions on Tweet view to perform various actions. For example, you may want to show a webview with the Tweet details when a user taps the Tweet view.
To respond to delegate methods, implement the TWTRTweetViewDelegate
protocol:
// MyViewController.h
#import <TwitterKit/TwitterKit.h>
@interface
MyViewController : UIViewController
<TWTRTweetViewDelegate>
@end
// MyViewController.m
@implementation
MyViewController : UIViewController
<TWTRTweetViewDelegate>
// My stuff
@end
|
Implement these optional methods as needed:
tweetView:didSelectTweet:
- (
void
)tweetView:(TWTRTweetView *)tweetView
didSelectTweet:(TWTRTweet *)tweet {
NSLog
(@
"log in my app that user selected tweet"
);
}
|
// Swift
func tweetView(tweetView: TWTRTweetView!, didSelectTweet tweet: TWTRTweet!) {
println(
"Tweet selected: \(tweet)"
)
}
|
tweetView:didTapURL:
// Objective-C
- (
void
)tweetView:(TWTRTweetView *)tweetView didTapURL:(
NSURL
*)url {
// Open your own custom webview
MyWebViewController *webViewController = [MyWebViewController alloc] init];
// *or* Use a system webview
UIViewController *webViewController = [[UIViewController alloc] init];
UIWebView *webView = [[UIWebView alloc] initWithFrame:webViewController.view.bounds];
[webView loadRequest:[
NSURLRequest
requestWithURL:url]];
webViewController.view = webView;
[
self
.navigationController pushViewController:webViewController animated:
YES
];
}
|
// Swift
func tweetView(tweetView: TWTRTweetView!, didTapURL url:
NSURL
!) {
// Open your own custom webview
let webViewController = MyWebViewController()
// *or* Use a system webview
let webViewController = UIViewController()
let webView = UIWebView(frame: webViewController.view.bounds)
webView.loadRequest(
NSURLRequest
(URL: url))
webViewController.view = webView
self
.navigationController!.pushViewController(webViewController, animated:
true
)
}
|
tweetView:willShareTweet:
// Objective-C
- (
void
)tweetView:(TWTRTweetView *)tweetView willShareTweet:(TWTRTweet *)tweet {
// Log to my analytics that a user started to share a tweet
NSLog
(@
"Tapped share for tweet: %@"
, tweet);
}
|
// Swift
func tweetView(tweetView: TWTRTweetView!, willShareTweet tweet: TWTRTweet!) {
println(
"Tapped share for tweet: \(tweet)"
)
}
|
tweetView:didShareTweet:withType:
// Objective-C
- (
void
)tweetView:(TWTRTweetView *)tweetView didShareTweet:(TWTRTweet *)tweet withType:(
NSString
*)shareType {
// Log to to my analytics that a user shared a tweet
NSLog
(@
"Completed share: %@ for tweet: %@"
, shareType, tweet);
}
|
// Swift
func tweetView(tweetView: TWTRTweetView!, didShareTweet tweet: TWTRTweet!, withType shareType: String!) {
println(
"Completed share: \(shareType) for tweet: \(tweet)"
)
}
|
tweetView:cancelledShareTweet:
- (
void
)tweetView:(TWTRTweetView *)tweetView cancelledShareTweet:(TWTRTweet *)tweet {
// Log to to my analytics that a user cancelled a share
NSLog
(@
"Cancelled share for tweet: %@"
, tweet);
}
|
// Swift
func tweetView(tweetView: TWTRTweetView!, cancelledShareTweet tweet: TWTRTweet!) {
println(
"Cancelled share for tweet: \(tweet)"
)
}
|
Using Static JSON for Tweets
We also expose the option of constructing TWTRTweet objects from a standard JSON dictionary for applications that have already obtained the necessary Twitter API response via other means.
// Objective-C
// Create a single tweet model object from JSON
TWTRTweet *tweet = [[TWTRTweet alloc] initWithJSONDictionary:dictionary];
// Create an array of tweet model objects from a JSON array
NSArray
*tweets = [TWTRTweet tweetsWithJSONArray:array];
|
// Swift
// Create a single tweet model object from JSON
let tweet = TWTRTweet(JSONDictionary: dictionary)
// Create an array of tweet model objects from a JSON array
let tweets = TWTRTweet.tweetsWithJSONArray(array)
|
Compose Tweets
The TWTRComposer
class presents a view to the user to compose Tweets. It provides methods to optionally configure the contents of the Tweet composition prior to presenting it.
![](https://g.twimg.com/dev/documentation/image/compose_tweet.png)
Presenting & Configuring the Composer
You can set the initial content before presenting the composer to the user. Methods that set the content of a Tweet return a Boolean value; they return NO if the composer has already been presented. The completion handler has a single parameter which you can use to determine the result of the Tweet composition.
// Objective-C
TWTRComposer *composer = [[TWTRComposer alloc] init];
[composer setText:@
"just setting up my Fabric"
];
[composer setImage:[UIImage imageNamed:@
"fabric"
]];
[composer showWithCompletion:^(TWTRComposerResult result) {
if
(result == TWTRComposerResultCancelled) {
NSLog
(@
"Tweet composition cancelled"
);
}
else
{
NSLog
(@
"Sending Tweet!"
);
}
}];
|
// Swift
let composer = TWTRComposer()
composer.setText(
"just setting up my Fabric"
)
composer.setImage(UIImage(named:
"fabric"
))
composer.showWithCompletion { (result) -> Void in
if
(result == TWTRComposerResult.Cancelled) {
println(
"Tweet composition cancelled"
)
}
else
{
println(
"Sending tweet!"
)
}
}
|
Note
Once a given instance ofTWTRComposer
has been shown, it cannot be reused; you must create a new instance ofTWTRComposer
every time you present it to the user.
Note
TWTRComposer
relies on the existence of a local Twitter account from the Accounts.framework. If no account exists, attempting to show the composer will prompt the user to go to Settings and add a Twitter account.
Digits: Sign in with Phone Number
Digits lets people create an account or sign into your app using nothing but their phone number on iOS and Android. Built using the same global, reliable infrastructure Twitter uses, Digits will verify the user’s phone number with a simple customizable user interface that easily integrates into your app.
Digits extends your existing user/profile database. A successful Digits account creation will return a stable userID to attach or match with your user record, and an oAuth token for the device. A verified phone number is also returned for convenience, but the user’s number may change at any time and should not be used for authentication.
Digits includes web login and signup support, as well as the ability for users to find their friends via their address books.
Release notes:
- Phone numbers are rate limited to normal consumer usage.
Set up Digits Authentication
Digits offers two ways to kick off the authentication flow: using a pre-configured button, or calling an authentication method from your own button’s tap handler.
Using the pre-configured button
In the view controller that will display the button, instantiate the pre-configured button DGTAuthenticateButton
after the view is loaded (e.g. in the viewDidLoad
method) and provide a completion block to handle the provided session object:
- (
void
)viewDidLoad {
DGTAuthenticateButton *digitsButton =
[DGTAuthenticateButton buttonWithAuthenticationCompletion:^
(DGTSession *session,
NSError
*error) {
// Inspect session/error objects
}];
[
self
.view addSubview:digitsButton];
}
|
// Swift
override func viewDidLoad() {
let digitsButton = DGTAuthenticateButton(
authenticationCompletion: { (session, error) in
// Inspect session/error objects
})
self
.view.addSubview(digitsButton)
}
|
This will render a button that looks like:
![](https://g.twimg.com/dev/documentation/image/digits_button.png)
Using your own button
In the view controller that displays your custom button, capture a tap event as usual and call the authenticateWithCompletion:
method with the completion block that handles the session object:
- (
void
)didTapButton {
[[Digits sharedInstance] authenticateWithCompletion:^
(DGTSession* session,
NSError
*error) {
if
(session) {
// Inspect session/error objects
}
}];
}
|
// Swift
func didTapButton(sender: AnyObject) {
let digits = Digits.sharedInstance()
digits.authenticateWithCompletion { (session, error) in
// Inspect session/error objects
}
}
|
Digits: Find Your Friends
Using the “Find Your Friends” feature, users can upload their address book to find other Digits users in your app that they know.
Getting started
The “Find Your Friends” feature is accessible through the DGTContacts
class. Provide the initializer with a user session of the type DGTSession
, which can be obtained from the Digits shared instance [Digits sharedInstance].session
.
To start the “Find Your Friends” process call one of the startContactsUploadWith...
methods. Variations are available to override properties such as custom appearance, title, or presenting view controller.
// Objective-C
DGTSession *userSession = [Digits sharedInstance].session;
DGTContacts *contacts = [[DGTContacts alloc] initWithUserSession:userSession];
[contacts startContactsUploadWithCompletion:^(DGTContactsUploadResult *result,
NSError
*error) {
// Inspect results and error objects to determine if upload succeeded.
}];
|
// Swift
let userSession = Digits.sharedInstance().session;
let contacts = DGTContacts(userSession: userSession);
contacts.startContactsUpload() { result, error in
// Inspect results and error objects to determine if upload succeeded.
}
|
![](https://g.twimg.com/dev/documentation/image/digits_find_friends.png)
Address book access
The first time startContactsUploadWith...
is called, Digits will display a modal UI requesting permission to upload the user’s address book.
Permissions control flow
If the user taps “OK”, the user will be prompted by the system for Address Book permission. If the user grants permission, their address book will uploaded in the background and the modal UI will dismiss immediately.
If the user taps “Not now”, the modal UI will dismiss and Digits will report DGTErrorCodeUserCanceledFindContacts
to the callback’s error argument.
If the user taps “OK”, but then does not grant your app access to their address book, the modal UI will dismiss and Digits will report DGTErrorCodeUserDeniedAddressBookAccess
to the callback’s error argument.
Note:
Subsequent calls to
startContactsUploadWith...
will not display the modal UI if the user has previously granted or denied access to their address book. If the user tapped “Not now”, then the modal UI will be displayed again. Call-[DGTContacts contactsAccessAuthorizationStatus]
to determine whether or not the modal UI will display.
Once the address book upload finishes, the provided callback will be called containing a DGTContactsUploadResult
object or an error that occurred. The DGTContactsUploadResult
object contains properties for totalContacts
and numberOfUploadedContacts
to describe how many contacts were uploaded and how many were actually uploaded successfully. Note that the DGTContactsUploadResult
object will be nil
if the upload fails.
Finding matches
Once a user has uploaded their contacts, Digits can lookup address book matches with other Digits users by calling lookupContactMatchesWithCursor:completion:
. Matches will return the Digits userID’s of users of your app that the authenticated user knows and any other users of your app that may know your user.
The optional cursor argument can be used to offset the returned matches from a prior request. For example, if after the first request the nextCursor
in the callback is not nil and 100 matches were found, pass the given nextCursor
to a second call of this method to retrieve the second 100 matches (if any).
// Objective-C
DGTSession *userSession = [Digits sharedInstance].session;
DGTContacts *contacts = [[DGTContacts alloc] initWithUserSession:userSession];
[contacts lookupContactMatchesWithCursor:
nil
completion:^(
NSArray
*matches,
NSString
*nextCursor,
NSError
*error) {
// matches is an Array of DGTUser objects
// use nextCursor in a follow-up call to this method to offset the results
}];
|
// Swift
let userSession = Digits.sharedInstance().session;
let contacts = DGTContacts(userSession: userSession);
contacts.lookupContactMatches(cursor:
nil
) { matches, nextCursor, error in
// matches is an Array of DGTUser objects
// use nextCursor in a follow-up call to this method to offset the results
}
|
Deleting uploaded contacts
All of a user’s uploaded contacts can be deleted from Digits by calling deleteAllUploadedContactsWithCompletion
.
Note:
After deleting a user’s contacts, calling lookupContactMatchesWithCursor:completion may still return matches. This is because of reverse lookup - if another Digits user has this user’s phone number in their address book, it would still be a match.
// Objective-C
DGTSession *userSession = [Digits sharedInstance].session;
DGTContacts *contacts = [[DGTContacts alloc] initWithUserSession:userSession];
[contacts deleteAllUploadedContactsWithCompletion:^(
NSError
*error) {
// Inspect error to determine if delete succeeded
}];
|
// Swift
let userSession = Digits.sharedInstance().session;
let contacts = DGTContacts(userSession: userSession);
contacts.deleteAllUploadedContacts() { error in
// Inspect error to determine if delete succeeded
}
|
Theming Digits
You can make Digits look and feel like your app by adding a theme. Digits uses DGTAppearance
instances to specify the style of the Digits UI elements.
DGTAppearance
has the properties backgroundColor
and accentColor
. The remaining colors are derived from these two colors.
- Background Color: The background color for all views in the Digits flow.
- Accent Color: This determines the main color of elements associated with user actions (e.g. buttons).
For example, if you have set up a custom button with the tap handler didTapButton
:
// Objective-C
- (
void
)didTapButton {
// Create an already initialized DGTAppearance object with standard colors:
DGTAppearance *digitsAppearance =
[[DGTAppearance alloc] init];
// Change color properties to customize the look:
digitsAppearance.backgroundColor = [UIColor
colorWithRed:81/255.
green:208/255.
blue:90/255.
alpha:1];
digitsAppearance.accentColor =
[UIColor redColor];
// Start the authentication flow with the custom appearance. Nil parameters for default values.
Digits *digits = [Digits sharedInstance];
[digits authenticateWithDigitsAppearance:digitsAppearance
viewController:
nil
title:
nil
completion:^(DGTSession *session,
NSError
*error) {
// Inspect session/error objects
}];
}
|
// Swift
func didTapButton(sender: AnyObject) {
// Create and initialize a DGTAppearance object with standard colors:
let digitsAppearance = DGTAppearance()
// Change color properties to customize the look:
digitsAppearance.backgroundColor = UIColor.blackColor()
digitsAppearance.accentColor = UIColor.greenColor()
// Start the authentication flow with the custom appearance. Nil parameters for default values.
let digits = Digits.sharedInstance()
digits.authenticateWithDigitsAppearance(digitsAppearance, viewController: nil, title: nil) { (session, error) in
// Inspect session/error objects
}
}
|
![](https://g.twimg.com/dev/documentation/image/digits_theming_light.png)
![](https://g.twimg.com/dev/documentation/image/digits_theming_dark.png)