iPhone SDK: Connect to Twitter with OAuth

iPhone SDK: Connect to Twitter with OAuth

Tutorial Details
  • Technology: iOS SDK
  • Difficulty: Intermediate
  • Completion Time: 45 Minutes
  • Software: Xcode 4

This tutorial will show you how to quickly integrate the Twitter API with the iPhone SDK using Twitter-OAuth-iPhone, a plug-and-play Twitter library for the iPhone composed of multiple open-source projects combined and synthesized for ease of implementation by Ben Gottlieb.

Subsequent Changes to Techniques & Software

Certain aspects of applications or techniques used in this tutorial have changed since it was originally published. This might make it a little difficult to follow along. We'd recommend looking at these more recent tutorials on the same topic:

NOTE: With the release of iOS 5, this article is now outdated. Moving forward, you should seriously consider using the Twitter Framework that ships with the iOS 5 SDK. Only consider implementing the solution demonstrated here if you must support users on older versions of iOS.

Project Setup

This tutorial will use a simple application called “TwitterRush” to demonstrate Twitter OAuth integration for the iPhone. By downloading the TwitterRush application, you will be able to precisely follow all steps in this tutorial. However, if you already have an iPhone project that you would like to connect with the Twitter API, you should still be able to follow along in your own code with only slight modifications.

In addition to TwitterRush or your own project, you will also need to download Ben Gottlieb’s Twitter-OAuth-iPhone project available on GitHub.

Step 1: Copy the Twitter+OAuth Folder

After downloading and unarchiving the Twitter-OAuth-iPhone library, drag the folder entitled “Twitter+OAuth” into the “Other Sources” folder in the Xcode 4 navigator area. Be sure to check the “Copy items into destination group’s folder (if needed)” option and click “Finish.”

Twitter API Guide 1

Trying to compile and run your application now will result in A LOT of errors (90 at the time of this writing with iOS SDK 4). Not to worry: we will easily fix all of them in Step 2.

Step 2: Add the libxml2 Library

In the navigator area of Xcode 4, select the project name (in this case “TwitterRush”). Next, select the current target (“TwitterRush” here again), and then select the “Build Phases” tab. Expand the “Link Binary With Libraries” option, and then click the “+” button to add a new framework. Type “libxml2″ into the search box, and select the libxml2.dylib library that appears in the list. Click “Add” to include this library in the linking phase of your project.

After completing these steps, your screen should look something like this:

Adding the libxml2 library to an Xcode 4 project

After adding the library to your project, you will need to modify the “header search paths” setting in your project’s build settings. To do this, deselect the target and select the actual TwitterRush Project. Open the “Build Settings” tab and search for the “Header Search Paths” entry. Double click this setting and then click the “+” button in the bottom left of the pop-up dialogue to add a new search path. Click the “recursive” check box, double click the “Path” field, and enter the following dynamic path:

$(SDKROOT)/usr/include/libxml2

After clicking “Done”, your screen should look similar to this:

Twitter API Guide 4

If you run the application from the Xcode menubar, you should now be able to build the application without any compile errors!

Step 3: Declare the NSXMLParserDelegate Protocol

While you are now able to compile and run the application without any errors, there are a number of warnings related to changes in the iOS4 SDK and the NSXMLParserDelegate protocol. You will need to explicitly declare that MGTwitterStatusesParser.h and MGTwitterXMLParser.h conform to this protocol in order to prevent these warnings from occurring.

To do so, open the MGTwitterStatusesParser.h file and modify the @interface declaration by declaring the NSXMLParserDelegate protocol like so:

@interface MGTwitterStatusesParser : MGTwitterXMLParser <NSXMLParserDelegate> {

Now do the same for MGTwitterXMLParser.h, modifying the @interface declaration to read:

@interface MGTwitterXMLParser : NSObject <NSXMLParserDelegate> {

You should now be able to smoothly compile the application without generating any errors or warnings! We’re now ready to begin integrating the Twitter-OAuth-iPhone library with our code.

Step 4: Import SA_OAuthTwitterController.h & Declare SA_OAuthTwitterEngine

We now need to begin importing the library classes that we will use to connect with the Twitter API. Open TwitterRushViewController.h and modify the code to read as follows:

#import <UIKit/UIKit.h>
#import "SA_OAuthTwitterController.h"
@class SA_OAuthTwitterEngine;
@interface TwitterRushViewController : UIViewController <UITextFieldDelegate, SA_OAuthTwitterControllerDelegate>
{
	IBOutlet UITextField     *tweetTextField;
	SA_OAuthTwitterEngine    *_engine;
}
@property(nonatomic, retain) IBOutlet UITextField *tweetTextField;
-(IBAction)updateTwitter:(id)sender;
@end

On line 2, we import the SA_OAuthTwitterController class for use within our view controller. On line 4, we forward declare the SA_OAuthTwitterEngine class so we can declare an instance of that class in the @interface without actually importing the header file. On line 6 we declare the SA_OAuthTwitterControllerDelegate protocol -this will allow us to easily respond to Twitter API events later. Finally, on line 10 we declare the _engine object as an instance of the SA_OAuthTwitterEngine class.

Now switch to the TwitterRushViewController.m file. Import the SA_OAuthTwitterEngine class that we just forward declared in the class interface:

#import "SA_OAuthTwitterEngine.h"

Because the SA_OAuthTwitterControllerDelegate only contains optional method declarations, at this point you should again be able to compile and run your application without any errors or warnings.

Step 5: Define Your Twitter API OAuth Credentials

In order to gain OAuth access to the Twitter API, you will need to first create a Consumer Key and a Secret Key for Twitter to be able to identify and authenticate your application. You can do this from the Twitter web site by logging into your account and navigating to the app registration form. When going through the registration process, be sure to specify “client” as the application type, check the “Yes, use Twitter for login” box, and select “Read & Write” as the default access type to enable your iPhone app to post tweets on behalf of your users.

After you have registered your application and Twitter has generated your application credentials, add the following to TwitterRushViewController.m above the class @implementation:

#define kOAuthConsumerKey        @"Your consumer key here"         //REPLACE With Twitter App OAuth Key
#define kOAuthConsumerSecret    @"Your consumer secret here"     //REPLACE With Twitter App OAuth Secret

We will use these constants momentarily when we instantiate our _engine object.

Step 6: Launch the Twitter Login Screen

For our use-case, we want to initialize the _engine object when our ViewController is created and then display the Twitter OAuth login screen as soon as the view controller finishes loading. To initialize the _engine object, modify the viewDidAppear method to read as follows:

- (void)viewDidAppear: (BOOL)animated {
	if(!_engine){
		_engine = [[SA_OAuthTwitterEngine alloc] initOAuthWithDelegate:self];
		_engine.consumerKey    = kOAuthConsumerKey;
		_engine.consumerSecret = kOAuthConsumerSecret;
	}
}

Now go ahead and release the _engine object in our view controller’s dealloc method:

- (void)dealloc {
	[_engine release];
	[tweetTextField release];
    [super dealloc];
}

After our view finishes loading, we want to immediately launch the Twitter login screen. To do so, you will need to again modify the viewDidAppear method like so:

- (void)viewDidAppear: (BOOL)animated {
	if(!_engine){
		_engine = [[SA_OAuthTwitterEngine alloc] initOAuthWithDelegate:self];
		_engine.consumerKey    = kOAuthConsumerKey;
		_engine.consumerSecret = kOAuthConsumerSecret;
	}
	UIViewController *controller = [SA_OAuthTwitterController controllerToEnterCredentialsWithTwitterEngine:_engine delegate:self];
	if (controller){
		[self presentModalViewController: controller animated: YES];
	}
}

If you run the application now, you’ll see that we are successfully presenting the Twitter login screen whenever our custom view is displayed. However, there is one major problem with this setup: the login screen will always be displayed when the view appears, even if the user has already logged in. We need to add a conditional that will only display this control if the user has not yet been connected via OAuth.

To do this, add the following conditional before displaying the view:

	if(![_engine isAuthorized]){
	    UIViewController *controller = [SA_OAuthTwitterController controllerToEnterCredentialsWithTwitterEngine:_engine delegate:self];
	    if (controller){
		    [self presentModalViewController: controller animated: YES];
	    }
	}

The isAuthorized method will return a boolean value of TRUE if we have an OAuth authentication token. So, this conditional simply tests whether we do not have authorization, and then displays the Twitter login when needed.

For the isAuthorized method to work, we also need to add the following SA_OAuthTwitterEngineDelegate protocol methods responsible for storing our OAuth authentication token after the first login:

//=============================================================================================================================
#pragma mark SA_OAuthTwitterEngineDelegate
- (void) storeCachedTwitterOAuthData: (NSString *) data forUsername: (NSString *) username {
	NSUserDefaults			*defaults = [NSUserDefaults standardUserDefaults];
	[defaults setObject: data forKey: @"authData"];
	[defaults synchronize];
}
- (NSString *) cachedTwitterOAuthDataForUsername: (NSString *) username {
	return [[NSUserDefaults standardUserDefaults] objectForKey: @"authData"];
}

Step 7: Post Updates to Twitter

In what is perhaps the simplest step of the entire process, add the following single line of code to updateTwitter, our custom IBAction method, to actually post an update to Twitter:

[_engine sendUpdate:tweetTextField.text];

Voila! You should now be posting updates to your Twitter feed. However, we aren’t quite finished yet. What happens if our application fails to post the update? What if we wanted to present a confirmation view if the tweet is posted successfully? Thankfully, the TwitterEngineDelegate protocol has two methods defined for just this purpose.

Add the following code to TwitterRushViewController.m:

//=============================================================================================================================
#pragma mark TwitterEngineDelegate
- (void) requestSucceeded: (NSString *) requestIdentifier {
	NSLog(@"Request %@ succeeded", requestIdentifier);
}
- (void) requestFailed: (NSString *) requestIdentifier withError: (NSError *) error {
	NSLog(@"Request %@ failed with error: %@", requestIdentifier, error);
}

You can see that the application will now log success and failure messages to the console depending on what happens after we click the “Tweet” button. This behavior can be easily modified to match the needs of your own apps.

Conclusion

If you have followed the step-by-step instructions above, you should now be able to post status updates to Twitter on behalf of your users!

The full TwitterRushViewController.h file should now look like this:

#import <UIKit/UIKit.h>
#import "SA_OAuthTwitterController.h"
@class SA_OAuthTwitterEngine;
@interface TwitterRushViewController : UIViewController <UITextFieldDelegate, SA_OAuthTwitterControllerDelegate>
{
	IBOutlet UITextField *tweetTextField;
	SA_OAuthTwitterEngine *_engine;
}
@property(nonatomic, retain) IBOutlet UITextField *tweetTextField;
-(IBAction)updateTwitter:(id)sender;
@end

The full TwitterRushViewController.m file should read:

#import "TwitterRushViewController.h"
#import "SA_OAuthTwitterEngine.h"
/* Define the constants below with the Twitter
   Key and Secret for your application. Create
   Twitter OAuth credentials by registering your
   application as an OAuth Client here: http://twitter.com/apps/new
 */
#define kOAuthConsumerKey				@"Your Key Here"        //REPLACE With Twitter App OAuth Key
#define kOAuthConsumerSecret			@"Your Secret Here"    //REPLACE With Twitter App OAuth Secret
@implementation TwitterRushViewController
@synthesize tweetTextField;
#pragma mark Custom Methods
-(IBAction)updateTwitter:(id)sender
{
	//Dismiss Keyboard
	[tweetTextField resignFirstResponder];
	//Twitter Integration Code Goes Here
	[_engine sendUpdate:tweetTextField.text];
}
#pragma mark ViewController Lifecycle
- (void)viewDidAppear: (BOOL)animated {
	// Twitter Initialization / Login Code Goes Here
	if(!_engine){
		_engine = [[SA_OAuthTwitterEngine alloc] initOAuthWithDelegate:self];
		_engine.consumerKey    = kOAuthConsumerKey;
		_engine.consumerSecret = kOAuthConsumerSecret;
	}
	if(![_engine isAuthorized]){
	    UIViewController *controller = [SA_OAuthTwitterController controllerToEnterCredentialsWithTwitterEngine:_engine delegate:self];
	    if (controller){
		    [self presentModalViewController: controller animated: YES];
	    }
	}
}
- (void)viewDidUnload {
	[tweetTextField release];
	tweetTextField = nil;
}
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}
- (void)dealloc {
    [_engine release];
    [tweetTextField release];
    [super dealloc];
}
//=============================================================================================================================
#pragma mark SA_OAuthTwitterEngineDelegate
- (void) storeCachedTwitterOAuthData: (NSString *) data forUsername: (NSString *) username {
	NSUserDefaults			*defaults = [NSUserDefaults standardUserDefaults];
	[defaults setObject: data forKey: @"authData"];
	[defaults synchronize];
}
- (NSString *) cachedTwitterOAuthDataForUsername: (NSString *) username {
	return [[NSUserDefaults standardUserDefaults] objectForKey: @"authData"];
}
//=============================================================================================================================
#pragma mark TwitterEngineDelegate
- (void) requestSucceeded: (NSString *) requestIdentifier {
	NSLog(@"Request %@ succeeded", requestIdentifier);
}
- (void) requestFailed: (NSString *) requestIdentifier withError: (NSError *) error {
	NSLog(@"Request %@ failed with error: %@", requestIdentifier, error);
}
@end

Thanks for reading this tutorial on the Twitter-OAuth-iPhone library, and a very special thanks to Ben Gottlieb, Matt Gemmell, Jon Crosby, Chris Kimpton, and Isaiah Carew. Without their hard work, implementing the Twitter API with the iPhone SDK would take many, many more steps to achieve.

Have questions or comments on this tutorial? Leave them in the comments section below or message @markhammonds directly on twitter. Bonus points for completing this tutorial and using the TwitterRush application to send me a shout out!

Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • kawsar

    Hi,
    Thanks for the great tutorial.
    How can i get the Friends list or Followers list from the Twitter iphone SDK API classes. ??

    • http://www.sabintsev.com Arthur

      Have you had any luck figuring this out? It seems that the MGTwitterEngine doesn’t supports a now deprecated API for this.

  • evripidis

    Is this still working? Cause it doesn’t seems to

  • http://www.clicktickboom.com Bezza

    Hi

    Do you have any idea when the update/new tutorial for implementing twitter using iOS 5 will land? I have an app I wish to integrate twitter in and want to do it the iOS5 way if possible.

    Cheers

    Bezza

    • http://mobile.tutsplus.com Mark Hammonds
      Author

      Probably mid November or early December. It’s in development!

  • binoj

    its really good!!but one thing , how the user can log out?here cancel button on twitter login page is not working.

    • Tony

      Did you realized how to do that?

  • Sam

    Hi,

    thanks for this great tutorial!

    I have a problem i cannot log in with my own twitter account, tried with a other that works but not mine.
    I am getting the Authorize App view again and again? Could it be problem that i created the Twitter App with my Account?

    Thanks

    • Sam

      Okay found the problem it is https after disabling it, it works. Any idee how to fix that?

      • Prabh

        have you been able to get fix for the problem?

  • http://www.flyingwisdomstudios.com Kenneth Chao

    Hi Mark, thanks for the tutorial. We would like to use the contents of:

    MGTwitterEngine

    within our App, but it is not clear what the licensing terms are, because of the numerous packages this is composed of? Can you clear this up? Can the entire contents of : X4-TwitterRushProjectCode.zip be used within a commercial app – free and clear?

    Cheers!
    -Ken

  • gagan joshi

    Hi this code works fine in IOS 4, but not working in IOS 5.

    Memory leaks in it. Please update it according to IOS 5.

  • http://www.obii.mobi marcus

    As noted: the correct way to do this for IOS 5 is to use the new library, but for older code, to be fixed.
    you simply need to change the SA_OAuthTwitterEngine.m search and replace twitter.com with api.twitter.com for the 3 request urls.

  • Paul

    Any code that works fine in iOs4 and 5???

  • http://www.evento.ae Umaid

    2011-12-02 13:43:37.165 TwitterRush[8798:12a03] PIPELINE: logging URLS that fail to support pipelining heuristics
    2011-12-02 13:43:37.166 TwitterRush[8798:12a03] PIPELINE: Heuristics failed for: http://www.google-analytics.com

    Build is crashing after changing the SA_OAuthTwitterEngine.m search and replace twitter.com with api.twitter.com for the 4 request urls. And doesnot work for me :( Any solution

    • mr multi codes

      Replace http://twitter.com with https://twitter.com in:

      self.requestTokenURL = [NSURL URLWithString: @"https://twitter.com/oauth/request_token"];
      self.accessTokenURL = [NSURL URLWithString: @"https://twitter.com/oauth/access_token"];
      self.authorizeURL = [NSURL URLWithString: @"https://twitter.com/oauth/authorize"];

  • Jas

    Hi, I have some problems after I add this project into my own project.

    The 4 errors are always regarding about the PIN
    (request for member ‘pin’ is something not a structure or union)
    as below:

    - (void) setPin: (NSString *) pin {
    [_pin autorelease];
    _pin = [pin retain];

    _accessToken.pin = pin;
    _requestToken.pin = pin;
    }

    I’ve done what users have suggested on stackoverflow.com but there are still these 4 errors.
    Can anyone please help! Thank you!

  • srinivas

    Hi
    Your tutorial helped me alot.but i have to get the follower names according to my requirements…is it possible to get the followers names.can you please suggest me…….

  • Anupama

    Libxml/xmlreader.h:No such file or directory…
    Am getting this error. Please help me. Am following the same procedure as given but also same problem is displayed.

  • Sudhir

    Thanks for tutorial. It is easy to understand.

    But, It has some problem like logout from twitter. Do you have any idea, how i logout from twitter.

    • DevGom

      if wish logout …

      NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
      [defaults defaults removeObjectForKey:@"authData"];
      [defaults synchronize];

      and this tutorial project try twitter log-in

      but I recommand keychain store

      • Sam

        Logout ist not working for me as i thought with this it askes for twitter credentials after killng and restarting the App. Can it be done on runtime?

        Thanks

  • umar

    Libxml/xmlreader.h:No such file or directory…
    Am getting this error. Please help me. Am following the same procedure as given but also same problem is displayed.

  • DevGom

    Good Tutorial~ Thanks, but iOS5 is repeated auth…

  • mohammad

    why in iOS5 is repeated auth…

  • Venkatesh

    Hi,Great tutorial , but i wanted to have my own native login page instead of the web view of twitter login page . is there any possibility for that . Please help me in this .

  • Rani

    Thanks alot.Its a great post.But I got a compilation error as:: Argument list too long: recursive header expansion failed at /Developer/Applications/Utilities/Application Loader.app/Contents/MacOS/itms/share/iTMSTransporter.woa/Contents/Library.

    Please fix the error

  • http://xcodenoobies.blogspot.com Rocotilos

    Hi there.

    Thanks so much for this tutorial. I am using XCode 4.2.1, tested on iPhone Sim 5.0 it works marvelously.
    Anyway I thought I share with all of you if you want to tweet with a single button click, add this delegate to your code:
    - (void)OAuthTwitterController:(SA_OAuthTwitterController *)controller
    authenticatedWithUsername:(NSString *)username

    This delegate will always be called once a login is successful. You can use the “username” as well if you wish. Or you can directly send a tweet in this delegate.

    Cheers
    Roco

  • Saketh

    For the following error “Libxml/xmlreader.h:No such file or directory…” Do the following.
    At header search path instead of $(SDKROOT)/usr/include/libxml2 place only /usr/include/libxml2

    for the another error “Argument list too long: recursive header expansion failed at /Developer/Applications/Utilities/Application Loader.app/Contents/MacOS/itms/share/iTMSTransporter.woa/Contents/Library.” Uncheck the recursive button beside library search path

    • nirmit

      hi i ahave done as u told but its giving same error libxml/xmlreader.h file not found
      #import “MGTwitterEngineGlobalHeader.h”
      #include

  • Thomas

    I have login and authorize apps. however , when I tweet. I get the error
    Error Domain=HTTP Code=401 “The operation couldn’t be completed. (HTTP error 401.)”
    do I error in some settings?

  • Mirza

    This is fantastic! :-) 2 thumbs up!

    • Nirmit

      its givng me arror tht libxml/xmlreader.g not found …please help me out

  • http://www.showmyband.com Zapra Gartiast

    It seems lot of errors in iOS 5.
    I get 9 Warning and 15 Error.
    The warning and error is “Semantic Issues”
    Anyone have a solutions or get the error like that?

  • help~~

    2012-04-19 14:39:28.954 TwitterRush[5115:707] Request 89E08123-A9A5-4E64-B9AB-7B541E1339D4 failed with error: Error Domain=HTTP Code=401 “The operation couldn‚Äôt be completed. (HTTP error 401.)”

  • Maher

    Nice tutorial. In my app I need just to post a tweet on the client’s account so I want to test if the client is logged not in the viewDidAppear but in the IBAction on pressing the tweet button. So the scenario is after pressing if it’s logged I’ll show him a view with the ne tweet and he’ll decide wether to post or not. And if the client isn’t logged, then I’ll show him the authentification view. Any idea how can I manage to do it. Thanks.

  • nirmti

    ita great but giving error libxml/xmlredear.hnot found please help mw out anyone

  • poonam

    i am a beginner. I had tried this tutorial everything is fine up-to coding part.but when i am trying to build and run it shows only textField and tweet button which we have added in xib.not twitters window or anything .what’s going wrong? pls help me.

  • https://www.rapidvaluesolutions.com Nithin George

    Hi,
    This is a good tutorial. But after the twitter login its redirecting to the callback url and showing the error “Invalid twitter oAuth request”. So it would be great if you suggest the solution

  • http://relaxiapps.com Ross

    Thanks for the bright red disclaimer at the top of the page, this has saved me much faffing about : ) I’ll go look for the Twitter Framework tutorial, I guess it must be on here by now…. somewhere.

  • Xin Liang

    Thank you very much for posting this excellent tutorial!
    I am very happy to find this tutorial.
    it saved my a lot of time to integrate Twitter into my app.

    I have one question to you.
    If I use this sdk(OAuth), iOS 5 upwards won’t have any issues to work?
    this is just one for iOS 4 SDK?
    please let me clarify with this problem.
    Respectufully

  • Ambili

    Thanx 4 the tutorial.
    Is there any way I can retrieve twitter user’s email Id via API? I am looking forward to implement in iOS.

    If twitter doesn’t provide any API, then how does foursquare retrieve them?
    1) Foursquare has provision to list out the user’s foursquare-friends who have registered with twitter.
    2) It also provides API which shows friends of users who commonly appear in ‘foursquare friend’s list’ as well as ‘twitter followers list’ of the user.

    In both the above cases comparison can be made only through email.
    Please help.

  • sahil bajaj

    how to fetch twitter user id in ios sdk programmatically……????

  • anil

    i can able login. but when i tap on Authorize app. the activity indicator is just animating by saying please wait… it was not redirecting to my app viewController.. please guide me..

    • http://mobile.tutsplus.com Mark Hammonds
      Author

      With the release of iOS 6, this post is largely outdated and you should be using either the Twitter or Social framework to accomplish Twitter integration in your apps. See the disclaimer at the top of this post for links to more recent content.

  • Pearlya

    Hi,
    I was done with this integration & was able to post tweet in my twitter account. It was working well. I also integrate this in my own project. But from yesterday, it is showing a message “The request token for this page is invalid. It may have already been used, or expired because it is too old. Please go back to the site or application that sent you here and try again; it was probably just a mistake.” I didnt make any change in my code.
    Any suggestion please?

    • http://mobile.tutsplus.com Mark Hammonds
      Author

      Hey Pearlya, you should switch to the Twitter Framework. See the links at the top of this post for two tutorials on Mobiletuts+ about how to do so.

  • dilaver

    sweet.. sweet..

  • pj

    the authentication is too long.as if it does not work

  • Fernando Salcido.

    Hi guys, y have a issue with iphone 6.0 simulator, never authorize the app?
    Someone have the same issue?
    Thanks in adavance.