Implementing Twitter Search iOS App Using AFNetworking, UITableView and MBProgressHUD
In this article we are going to implement a simple Twitter search app which will enable the user to search Twitter feeds for the keywords. We will be utilizing AFNetworking API, UITableView and the MBProgressHUD libraries in this article.
Setting Up the User Interface:
For this app our user interface will be really simple. It will consist of a TextField where a user will enter the keyword, a Button which will be used to perform a search and a TableView which will be used to display the results. The interface is shown in the screenshot below:
Fetching the Tweets:
In one of the previous article we used ASIHTTPRequest class to make an HTTP request. We can still use ASIHTTPRequest class to fetch the feeds but for the sake of simplicity we are going to use AFNetworking class created by the people behind Gowalla. Create a new Group in your iOS application and name is "AFNetworking". Place the files from the AFNetworking folder into the newly created "AFNetworking" folder.
You will also need to add the following frameworks to your project:
Compile your application and make sure everything builds successfully. Now it is time to fetch the tweets using the following URL:
The "%@" is the placeholder which will be replaced by the searched keyword that the user will enter. The populateTweetsWithSearch method is responsible for fetching the tweets and it is implemented below:
As soon as the AFJSONRequestOperation object is added to the NSOperationQueue the request is triggered. The AFJSONRequestOperation exposes the success and failure events which are triggered depending on the response received by the caller. Inside the success event we get the json associated with the request. The following code is used to iterate through the json "results" element and populate the tweets array:
Tweet.h is a simple class which represents a single tweet. The implementation is shown below:
At this point we have retrieved all the tweets associated with the searched keyword. In the next section we are going to display the tweets in a UITableView control.
NOTE: The Twitter API will only return the 15 most recents tweets. You can configure it to return more tweets but for this article we are going to stick with the default.
Populating the UITableView:
UITableView might be the most used control in the iOS library. It allows you to display the contents inside a single cell. Each cell is divided into an imageView, contentView and accessoryView. In this article we are going to utilize the imageView and contentView areas. The UITableView uses datasource to populate itself. This means we need to conform to the protocols exposed by the UITableViewDataSource. The two required methods which must be implemented when conforming to the UITableViewDataSource are listed below:
1) numberofRowsInSection 2) cellForRowAtIndexPath
The numberOfRowsInSection simply returns the total number of rows in the datasource. The cellForRowAtIndexPath returns a cell which is added to the UITableView control. The UITableViewDatasource delegate is implemented by our TweetViewController as shown below:
Also, make sure to connect the "datasource" property of the UITableView control to the FileOwner using the Interface Builder. You can also do this programmatically using the following code:
The implementation of numberOfRowsInSection is shown below:
Pretty simple! numberOfRowsInSection returns the total number of rows in the collection which in our case is the tweets array.
The cellForRowAtIndexPath is the method where all the fun happens. The cellForRowAtIndexPath is triggered each time a cell is requested by the UITableView control. The implementation is shown below:
The most important part of the above method is the use of UITableView's dequeueReusableCellWithIdentifier method:
The dequeueReusableCellWithIdentifier method is responsible for returning the same cell which has gone off screen. If you do not use dequeueReusableCellWithIdentifier and create a new UITableCell for each record associated with your collection then your app will lag in performance and eventually crash. The uniqueIdentifier is used to get a particular type of cell from the queued cells which have gone off screen. Only the textLabel and the imageView is rendered each time because their value is based on the items in the collection.
Even with the above usage of dequeueReusableCellWithIdentifier you will notice a little lag when scrolling through a list of items. If you want absolute smooth scrolling then create a new uniqueIdentifier each time user searches for a new record. This will result in the ultimate smooth scrolling. The code is shown below:
The screenshot is shown below:
At this point you have a working application! But there is one problem, whenever the user searches for a keyword the screen pauses and takes some time to load the tweets. It will be a good idea to show some sort of indication to the user that the tweets are being fetched. In the next section we are going to utilize MBProgressHUD API to create a progress indicator while the user waits for the tweets to be displayed.
Loading Avatars Asynchronously:
If you run the above application you will notice that it takes quite a bit of time to load the tweets. The main problem is that we are blocking the main thread while loading the avatars. In this section we are going to use SDWebImage library to load the avatars asynchronously. The updated code is shown below:
The setImageWithURL method of the imageView is a new category method added by the SDWebImage API and this allows us to asynchronously download the images. Run the app again and you will notice that now the tweets are fetched much faster and then avatars appears as soon as they are downloaded.
First download MBProgressHUD using this link. Create a new group in your application and name it "MBProgressHUD". Place the required files inside the new group. MBProgressHUD can be customized in different ways. For documentation please refer to the sample project which is included in the MBProgressHUD download. For our application the progress indicator should be displayed as soon as we click the search button and it should hide when the tweets are fetched successfully or when there is an error.
The implementation below shows the performSearch method which is fired when the user clicks on the search button:
And inside the success callback we hide the HUD as shown below:
The effect is shown below:
New section added for loading the avatars asynchronously using the SDWebImage library.
In this detailed article we implemented a simple twitter keyword search application. We learned about AFNetworking API, UITableView control and the MBProgressHUD progress indicator.