An iOS 10 Twitter Integration Tutorial using SLRequest
Previous | Table of Contents | Next |
iOS 10 Facebook and Twitter Integration using SLRequest | Making Store Purchases with the SKStoreProductViewController Class |
Learn SwiftUI and take your iOS Development to the Next Level |
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 with the product name set to TwitterApp. Set the Devices menu to Universal and the Language menu to Swift before creating the new project.
Designing the User Interface
Navigate to the Main.storyboard file in the project navigator panel and select it to load it into the Interface Builder. 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 105 1. With the Table View selected in the storyboard canvas, use the Auto Layout Add New Constraints menu to configure Spacing to nearest neighbor constraints on all four sides of the view with the Constrain to margins option disabled.
Learn SwiftUI and take your iOS Development to the Next Level |
Figure 105-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 along the top of the view canvas as outlined in Figure 105-2:
File:Xcode 8 ios 10 twitter example datasource
Figure 105-2
Repeat the steps to establish the same connection for the delegate outlet.
Modifying the View Controller Class
Before writing code to talk to the Twitter API, some additional frameworks 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 ViewController.swift file and modify it as follows:
import UIKit import Social import Accounts class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { @IBOutlet weak var tweetTableView: UITableView! var dataSource = [AnyObject]() . . .
Learn SwiftUI and take your iOS Development to the Next Level |
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 ViewController.swift file. Select this file and modify it to add the code for this new method:
func getTimeLine() { let account = ACAccountStore() let accountType = account.accountType( withAccountTypeIdentifier: ACAccountTypeIdentifierTwitter) account.requestAccessToAccounts(with: accountType, options: nil, completion: {(success, error) in if success { let arrayOfAccounts = account.accounts(with: accountType) if (arrayOfAccounts?.count)! > 0 { let twitterAccount = arrayOfAccounts?.last as! ACAccount let requestURL = URL(string: "https://api.twitter.com/1.1/statuses/user_timeline.json") let parameters = ["screen_name" : "@techotopia", "include_rts" : "0", "trim_user" : "1", "count" : "20"] let postRequest = SLRequest(forServiceType: SLServiceTypeTwitter, requestMethod: SLRequestMethod.GET, url: requestURL, parameters: parameters) postRequest?.account = twitterAccount postRequest?.perform(handler: {(responseData, urlResponse, error) in do { try self.dataSource = JSONSerialization.jsonObject(with: responseData!, options: JSONSerialization.ReadingOptions.mutableLeaves) as! [AnyObject] if self.dataSource.count != 0 { DispatchQueue.main.async() { self.tweetTableView.reloadData() } } } catch let error as NSError { print("Data serialization error: \(error.localizedDescription)") } }) } } else { print("Failed to access account") } }) }
Much of the code in this method will be familiar from the previous chapter. There are, however, some notable exceptions. First, the URL used in the request is intended to return the entries in the time line for a specific user’s Twitter account:
let requestURL = URL(string: "https://api.twitter.com/1.1/statuses/user_timeline.json")
The URL specified requires additional parameters specifying the Twitter user’s screen name and 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 for a user with the screen name @techotopia:
let parameters = ["screen_name" : "@techotopia", "include_rts" : "0", "trim_user" : "1", "count" : "20"]
Learn SwiftUI and take your iOS Development to the Next Level |
let postRequest = SLRequest(forServiceType: SLServiceTypeTwitter, requestMethod: SLRequestMethod.GET, URL: requestURL, parameters: parameters)
Finally, the handler code for the postRequest method call now accesses the returned Data object. The NSJSONSerialization class is then used to parse and serialize the data returned and assign it to the dataSource array 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?.perform(handler: {(responseData, urlResponse, error) in do { try self.dataSource = JSONSerialization.jsonObject( with: responseData!, options: JSONSerialization.ReadingOptions.mutableLeaves) as! [AnyObject] if self.dataSource.count != 0 { DispatchQueue.main.async() { self.tweetTableView.reloadData() } } } catch let error as NSError { print("Data serialization error: \(error.localizedDescription)") } })
Learn SwiftUI and take your iOS Development to the Next Level |
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 method call to the viewDidLoad method located in the ViewController.swift file. Now is also an opportune time to register the identifier of the table view cell that will be used to display the tweets and to assign an estimated row height for the table view cells:
override func viewDidLoad() { super.viewDidLoad() tweetTableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell") getTimeLine() tweetTableView.estimatedRowHeight = 50 }
The Table View Delegate Methods
At a minimum, the delegate for a Table View must implement the numberOfRowsInSection and tableView(_:cellForRowAt:) 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 ViewController.swift file, therefore, implement this method as follows:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return dataSource.count }
Learn SwiftUI and take your iOS Development to the Next Level |
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") let row = indexPath.row let tweet = self.dataSource[row] cell!.textLabel!.text = tweet.object(forKey: "text") as? String cell!.textLabel!.numberOfLines = 0 return cell! }
An additional point to note in the above method is the line which assigns a zero value to the numberOfLines property cell UILabel instance object. This ensures that the tweet text is displayed using line wrapping in the event that the tweet is longer than the width of the cell by informing the label that it can use as many lines as needed to display the text.
Building and Running the Application
Click on the run button located in the Xcode toolbar and wait for the application to launch. The application will then display the 20 most recent tweets posted to the specified account.
Figure 105-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.
Learn SwiftUI and take your iOS Development to the Next Level |
Previous | Table of Contents | Next |
iOS 10 Facebook and Twitter Integration using SLRequest | Making Store Purchases with the SKStoreProductViewController Class |