An iOS 7 Twitter Integration Tutorial using SLRequest

From Techotopia
Jump to: navigation, search
PreviousTable of ContentsNext
iOS 7 Facebook and Twitter Integration using SLRequestMaking Store Purchases with the iOS 7 SKStoreProductViewController Class


Purchase the fully updated iOS 10 / Swift 3 / Xcode 8 edition of this book in eBook ($19.99) or Print ($45.99) format.
iOS 10 App Development Essentials Print and eBook (ePub/PDF/Kindle) edition contains over 100 chapters. Learn more...

Buy eBook Buy Print Preview Book


Having covered much of the theory of using the Accounts framework and SLRequest class to integrate social networks into iOS applications in the previous chapter, this chapter will put this theory into practice by creating an application to request and display the entries in the timeline of a Twitter account.




Creating the TwitterApp Project

Begin by launching Xcode and selecting the options to create a new iOS application based on the Single View Application template. Enter TwitterApp as the product name and class prefix and set the device to either iPhone or iPad.

Designing the User Interface

Navigate to the Main.storyboard file in the project navigator panel and select it to load it into to the editing panel. From the Object Library panel, drag and drop a Table View component onto the view canvas and position it so that it fills the entire view space as shown in Figure 82-1.

Select the Table View object and display the Assistant Editor using View -> Assistant Editor -> Show Assistant Editor menu option and make sure that it is displaying the content of the TwitterAppViewController.h file. Ctrl-click on the Table View object in the view and drag the resulting line to the area immediately beneath the @interface directive in the Assistant Editor panel. Upon releasing the line, the connection panel will appear. Configure the connection as an Outlet named tweetTableView and click on the Connect button.


The user interface layout for an iOS 7 Twitter app example

Figure 82 1


With the Table View still selected, display the Connections Inspector (View -> Utilities -> Show Connections Inspector). Click on the circle to the right of the dataSource outlet and drag the line to the Twitter App View Controller icon in the bar beneath the view canvas as outlined in Figure 82-2:


Ios 7 twitter datasource connection.png

Figure 82-2


Repeat the steps to establish the same connection for the delegate outlet. With the table view still selected in the storyboard scene, select the Resolve Auto Layout Issues menu from the toolbar in the lower right hand corner of the storyboard panel and select the Reset to Suggested Constraints option.


Modifying the Interface File

Before writing code to talk to the Twitter API, some additional files need to be imported to avoid undefined symbols when we start working with the Accounts and SLRequest classes. In addition, an array is going to be needed to act as the data source for the application which will ultimately contain the tweets that are returned by the Twitter API. The compiler also needs to be notified that this class is acting as both the data source and delegate for the Table View.

Select the TwitterAppViewController.h file and modify it as follows:

#import <UIKit/UIKit.h>
#import <Accounts/Accounts.h>
#import <Social/Social.h>

@interface TwitterAppViewController : UIViewController
<UITableViewDataSource, UITableViewDelegate>

@property (strong, nonatomic) IBOutlet UITableView *tweetTableView;
@property (strong, nonatomic) NSArray *dataSource;
@end	

Accessing the Twitter API

The code to access the Twitter account and extract the posts from the account timeline will reside in a method named getTimeLine located in the TwitterAppViewController.m file. Select this file and modify it to add the code for this new method:

- (void)getTimeLine {
    ACAccountStore *account = [[ACAccountStore alloc] init];
    ACAccountType *accountType = [account   
    accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];

    [account requestAccessToAccountsWithType:accountType 
      options:nil completion:^(BOOL granted, NSError *error)
     {
         if (granted == YES)
         {
             NSArray *arrayOfAccounts = [account 
                      accountsWithAccountType:accountType];

             if ([arrayOfAccounts count] > 0)
             {
                 ACAccount *twitterAccount = 
                    [arrayOfAccounts lastObject];

                 NSURL *requestURL = [NSURL URLWithString:
          @"https://api.twitter.com/1.1/statuses/user_timeline.json"];

                 NSDictionary *parameters = 
                          @{@"screen_name" : @"@techotopia",
                          @"include_rts" : @"0",
                          @"trim_user" : @"1",
                          @"count" : @"20"};

                 SLRequest *postRequest = [SLRequest 
                      requestForServiceType:SLServiceTypeTwitter
                      requestMethod:SLRequestMethodGET
                      URL:requestURL parameters:parameters];

                 postRequest.account = twitterAccount;

                 [postRequest performRequestWithHandler:
                     ^(NSData *responseData, NSHTTPURLResponse 
                     *urlResponse, NSError *error)
                  {
                      self.dataSource = [NSJSONSerialization 
                          JSONObjectWithData:responseData 
                          options:NSJSONReadingMutableLeaves 
                          error:&error];

                      if (self.dataSource.count != 0) {
                          dispatch_async(dispatch_get_main_queue(), ^{
                              [self.tweetTableView reloadData];
                          });
                      }
                  }];
             }
         } else {
             // Handle failure to get account access
         }
     }];
}

Much of the code in this method will be familiar from the previous chapter. There are, however, some notable exceptions. Firstly, the URL used in the request is intended to return the entries in the time line of the user’s Twitter account:

NSURL *requestURL = [NSURL URLWithString:
          @"https://api.twitter.com/1.1/statuses/user_timeline.json"];

Purchase the fully updated iOS 10 / Swift 3 / Xcode 8 edition of this book in eBook ($19.99) or Print ($45.99) format.
iOS 10 App Development Essentials Print and eBook (ePub/PDF/Kindle) edition contains over 100 chapters. Learn more...

Buy eBook Buy Print Preview Book

The URL specified requires additional parameters specifying how much data is to be returned. In this case the request is limited to the 20 most recent posts and configured to include the tweet entities:

NSDictionary *parameters = @{@"screen_name" : @"@techotopia",
                             @"include_rts" : @"0",
                             @"trim_user" : @"1",
                             @"count" : @"20"};

The SLRequest object is primed to use the SLRequestMethodGET HTTP method. This is appropriate since this time we are getting, as opposed to posting, data:

SLRequest *postRequest = [SLRequest 
                      requestForServiceType:SLServiceTypeTwitter
                      requestMethod:SLRequestMethodGET
                      URL:requestURL parameters:parameters];

Finally, the handler code for the postRequest method call now accesses the returned NSData object. The NSJSONSerialization class is then used to parse and serialize the data returned and assign it to the dataSource NSArray object. The Table View object is then told to reload the data it is displaying, causing it to re-read the data in the dataSource array and display it to the user. An important point to note here is that iOS performs the Twitter API request in a different thread from the main thread of the application. Threads are the cornerstone of any multitasking operating system and can be thought of as mini-processes running within a main process, the purpose of which is to enable at least the appearance of parallel execution paths within applications.

Since user interface updates take place in the main thread of the application, code has been added to ensure that the Table View reload call is made in the main thread as opposed to the thread used for the post request:

[postRequest performRequestWithHandler:
                     ^(NSData *responseData, NSHTTPURLResponse 
                     *urlResponse, NSError *error)
                  {
                      self.dataSource = [NSJSONSerialization 
                          JSONObjectWithData:responseData 
                          options:NSJSONReadingMutableLeaves 
                          error:&error];

                      if (self.dataSource.count != 0) {
                          dispatch_async(dispatch_get_main_queue(), ^{
                              [self.tweetTableView reloadData];
                          });
                      }
                  }];

All that remains is to implement the delegate methods for the Table View so that the tweets are displayed to the user.

Calling the getTimeLine Method

Having implemented the getTimeLine method we need to make sure it gets called when the application is launched. This involves the addition of a single line of code to the viewDidLoad method located in the TwitterAppViewController.m file:

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self getTimeLine];
}

The Table View Delegate Methods

At a minimum, the delegate for a Table View must implement the numberOfRowsInSection and cellForRowAtIndexPath delegate methods. In terms of this example application, the former simply needs to return the number of items in the dataSource array. Remaining within the TwitterAppViewController.m file, therefore, implement this method as follows:

#pragma mark -
#pragma mark UITableViewDataSource

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return _dataSource.count;
}

The cellForRowAtIndexPath method, on the other hand, needs to extract the text of the tweet corresponding to the current table row from the dataSource array and assign it to the table cell. Since each tweet is stored in the array in the form of an NSDictionary object, the tweet object first needs to be extracted and then the entry matching the “text” key in the dictionary used to access the text:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [self.tweetTableView
             dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil) {
        cell = [[UITableViewCell alloc]
                initWithStyle:UITableViewCellStyleDefault 
                reuseIdentifier:CellIdentifier];
    }

    NSDictionary *tweet = _dataSource[[indexPath row]];

    cell.textLabel.text = tweet[@"text"];
    return cell;
}

Building and Running the Application

Click on the Run button located in the Xcode toolbar and wait for the application to launch either on a physical iOS device or the iOS Simulator. Assuming a Twitter account has been configured, the application will display the 20 most recent tweets posted to that account.


An iOS 7 Twitter App Running

Figure 82-3


Summary

In addition to posting entries, the SLRequest class can be used to retrieve information from supported social networks. In this chapter, a list of tweets posted to a Twitter account have been requested using the SLRequest class and displayed to the user within a Table View. The example also introduced the use of the NSJSONSerialization class to serialize the data returned from a Twitter API request.


Purchase the fully updated iOS 10 / Swift 3 / Xcode 8 edition of this book in eBook ($19.99) or Print ($45.99) format.
iOS 10 App Development Essentials Print and eBook (ePub/PDF/Kindle) edition contains over 100 chapters. Learn more...

Buy eBook Buy Print Preview Book



PreviousTable of ContentsNext
iOS 7 Facebook and Twitter Integration using SLRequestMaking Store Purchases with the iOS 7 SKStoreProductViewController Class