Retrieve list of Twitter followers using Swift

This article provides details about the the steps required to retrieve the followers in from your twitter account. You will learn the following by going through this article

  1. Use oAuth to retrieve bearer token.
  2. Retrieve twitter followers using API call.
  3. Last 20 followers name and profile image will be displayed in a tableview.

Download the source code from here.

201504202245.jpg

Consumer Key and Consumer Secret

First step is to register your app in apps.twitter.com and get the Consumer Key and Consumer Secret from Application Settings.

Service Wrapper

Now create a service wrapper which retrieves the bearer token and uses the retrieved token for the service call. In this example the service call will be made to retrieve followers of your Twitter account.

[code language=”swift”]public class TwitterServiceWrapper:NSObject {
let consumerKey = “”
let consumerSecret = “”
let authURL = “https://api.twitter.com/oauth2/token”
}[/code]

Create a TwitterServiceWrapper class with constants for storing the consumer key, consumer secret and oAuth URL. Replace the consumer_key and consumer_secret from your apps.twitter.com account. Next add the following function to retrieve the bearer token using base64 encoded string. We have used Application – only authentication for this example, for more info refer to this documentation.

[code language=”swift”]// MARK:- Bearer Token

func getBearerToken(completion:(bearerToken: String) ->Void) {
var request = NSMutableURLRequest(URL: NSURL(string: authURL)!)
request.HTTPMethod = “POST”
request.addValue(“Basic “ + getBase64EncodeString(), forHTTPHeaderField: “Authorization”)
request.addValue(“application/x-www-form-urlencoded;charset=UTF-8”, forHTTPHeaderField: “Content-Type”)
var grantType = “grant_type=client_credentials”
request.HTTPBody = grantType.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)

NSURLSession.sharedSession() .dataTaskWithRequest(request, completionHandler: { (data: NSData!, response:NSURLResponse!, error: NSError!) -> Void in

var errorPointer : NSErrorPointer = nil

if let results: NSDictionary = NSJSONSerialization .JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments , error: errorPointer) as? NSDictionary {

if let token = results[“access_token”] as? String {
completion(bearerToken: token)
} else {
println(results[“errors”])
}
}

}).resume()
}

// MARK:- base64Encode String

func getBase64EncodeString() -> String {

let consumerKeyRFC1738 = consumerKey.stringByAddingPercentEscapesUsingEncoding(NSASCIIStringEncoding)

let consumerSecretRFC1738 = consumerSecret.stringByAddingPercentEscapesUsingEncoding(NSASCIIStringEncoding)

let concatenateKeyAndSecret = consumerKeyRFC1738! + ”:” + consumerSecretRFC1738!

let secretAndKeyData = concatenateKeyAndSecret.dataUsingEncoding(NSASCIIStringEncoding, allowLossyConversion: true)

let base64EncodeKeyAndSecret = secretAndKeyData?.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.allZeros)

return base64EncodeKeyAndSecret!
}
[/code]

 

Now add the following functions which would use the bearer token to make the service call then process the results and store them in TwitterFollower struct.

[code language=”swift”]// MARK:- Service Call

func getResponseForRequest(url:String) {
var results:NSDictionary
getBearerToken({ (bearerToken) -> Void in
var request = NSMutableURLRequest(URL: NSURL(string: url)!)
request.HTTPMethod = “GET”
let token = “Bearer “ + bearerToken
request.addValue(token, forHTTPHeaderField: “Authorization”)

NSURLSession.sharedSession() .dataTaskWithRequest(request, completionHandler: { (data: NSData!, response:NSURLResponse!, error: NSError!) -> Void in

self.processResult(data, response: response, error: error)
}).resume()
})
}

// MARK:- Process results
func processResult(data: NSData, response:NSURLResponse, error: NSError?) {

var errorPointer : NSErrorPointer = nil

if let results: NSDictionary = NSJSONSerialization .JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments , error: errorPointer) as? NSDictionary {

if var users = results["users"] as? NSMutableArray {
for user in users {
let follower = TwitterFollower(name: user["name"] as! String, url: user["profile_image_url"] as! String)
self.delegate?.finishedDownloading(follower)
}

} else {
println(results["errors"])
}
}
}
[/code]

 

TwitterFollowerDelegate

We also need to create a protocol in TwitterServiceWrapper class. This will inform the delegates once the data is downloaded from the service

[code language=”swift”]protocol TwitterFollowerDelegate{
func finishedDownloading(follower:TwitterFollower)
}[/code]

TwitterFollower – Place holder struct

TwitterFollower struct will just act as a place holder for storing followers’s name, profile URL and description. TwitterFollower struct looks as shown below.

[code language=”swift”] struct TwitterFollower {
var name: String?
var description: String?
var profileURL: NSData?

init (name: String, url: String) {
self.name = name
let pictureURL = NSURL(string: url)
profileURL = NSData(contentsOfURL: pictureURL!)
}
}[/code]

Add TableViewController

Now finally we use the followers data retrieved from the service and displayed in a tableview. TwitterFollowerController is a UITableViewController which conforms to TwitterFollowerDelegate protocol. We create an instance of TwitterServiceWrapper class and pass the request URL for retrieving the followers details in viewDidLoad method.

[code language=”swift”]class TwitterFollowerController: UITableViewController, TwitterFollowerDelegate {
var serviceWrapper: TwitterServiceWrapper = TwitterServiceWrapper()
var followers = [TwitterFollower]()

@IBOutlet weak var activityIndicator: UIActivityIndicatorView!

override func viewDidLoad() {
super.viewDidLoad()
serviceWrapper.delegate = self
activityIndicator.startAnimating()
serviceWrapper.getResponseForRequest(“https://api.twitter.com/1.1/followers/list.json? screen_name=rshankra&skip_status=true&include_user_entities=false”)
}[/code]

Implement the Table View Data source methods as shown below

[code language=”swift”]// MARK: – Table view data source

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let numberOfRows = followers.count
return numberOfRows
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

let cell = tableView.dequeueReusableCellWithIdentifier(“reuseIdentifier”, forIndexPath: indexPath) as! UITableViewCell

let follower = followers[indexPath.row] as TwitterFollower
cell.imageView?.image = UIImage(data: follower.profileURL!)
cell.textLabel?.text = follower.name

return cell
}[/code]

The data for followers array will be populated in the TwitterFollowerDelegate method.

[code language=”swift”] // MARK: – TwitterFollowerDelegate methods

func finishedDownloading(follower: TwitterFollower) {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.followers.append(follower)
self.tableView.reloadData()
self.activityIndicator.stopAnimating()
self.activityIndicator.hidden = true
})
}[/code]

We need to make sure that the reloading of data is done in the main thread by calling

[code language=”plain”]dispatch_async(dispatch_get_main_queue()[/code]

Download the source code from here.


Comments

5 responses to “Retrieve list of Twitter followers using Swift”

  1. Excellent tutorial 😀

  2. Hi Ravi, great tutorial here. I’ve been trying to achieve the same thing myself to no avail using Twitter’s Fabric Kit. I’m assuming if using Fabric one wouldn’t need the bearertoken function that you use first. I’d love an answer. Cheers!

    P.S: I just followed you on twitter.

    1. Thanks David. Yes you wouldn’t need bearertoken function when using fabric.

      Regards,
      Ravi

      1. But one would need to declare the tokens right? This is what I’m having problems with. Haven’t much documentation to that effect. How does one declare them?

  3. Twitter followers is not working getting error on
    fatal error: unexpectedly found nil while unwrapping an Optional value

    do {

    if let results: NSDictionary = try NSJSONSerialization .JSONObjectWithData(data!, options: NSJSONReadingOptions.AllowFragments) as? NSDictionary

    {
    if let token = results[“access_token”] as? String {
    completion(bearerToken: token)
    } else {
    print(results[“errors”])
    }
    }

Leave a Reply to Andre Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.