Geeks With Blogs

News
Joe Mayo

A couple weeks ago, I posted LINQ to Twitter Runs Xamarin.Android. That was pretty exciting, but so is watching LINQ to Twitter jamming tweets into a UITableView in an iPhone simulator on my Mac, courtesy of Xamarin.iOS hosted in Visual Studio 2013. In this post I’ll show how you can do use LINQ to Twitter in Xamarin.iOS too. Since Xamarin now supports async and Portable Class Libraries (PCL) and LINQ to Twitter is async and PCL, this will work nicely.

Note: If you haven’t used the Xamarin tools before, visit the Xamarin site,download the free version, and do the Getting Started tutorial. You also need a Mac to serve as a compile and iPhone Simulator target.

Creating a Xamarin.iOS Project

When installing Xamarin, you get a plug-in for VS2013 that sets up project templates and other useful tools. I’ll be using VS2013, but you can also use Xamarin Studio, which is a nice tool too. If you use Xamarin Studio, you’ll have to use your Mac because the Windows version doesn’t support iOS development.

To get started, open VS2013 and select File | New | Project. You’ll see the New Project window below.

SNAGHTMLf7b664f

Under Installed Templates, Visual C#, iOS, iPhone, you see some new templates. Select HelloWorld Application, name the project L2TDemo, specify any file location you want, and click OK. That generates the following project:

SNAGHTMLf7ccb9c

This demo uses code to inject a TableView into the UI via the controller, MyViewController.cs. We won’t change Main.cs or AppDelegate.cs.

Before getting started, there are a couple important application settings to change. Press Shift+F6 to Build and observe the compiler errors in the Error List window. We’ll fix those problems now. First, double-click Info.plist and observe that Application name and Identifier are blank, which are two of the errors in the list. Set both fields to L2TDemo, press Shift+F5 and observe that the errors go away. The remaining compiler error is for pairing with the Mac, which you can do by the following steps:

  1. On the Mac, run the Xamarin.iOS Build Host and click Pair.
  2. On Windows, double-click the Connection… error message in the Error List window in Visual Studio.
  3. On Windows, select the Mac in the list of network devices. A new PIN window appears.
  4. Type in the PIN from the Mac into the Pin window in Visual Studio and click the Pair button.
  5. You should see a message to indicate that your Visual Studio is paired with the Mac.

There isn’t a requirement to join the Apple Developer program until you want to deploy to a physical device. You can use the simulator on the Mac, but you’ll encounter errors in the default deployment, which is set up to deploy to an iPhone. To fix this problem, locate the drop-down to the right of the Debug drop-down in the toolbar – the one with iPhone selected. Change that to iPhoneSimulator.

The next part of setting up your Visual Studio environment is to add a reference to LINQ to Twitter. As of this writing, LINQ to Twitter v3.0 beta is available for download from http://bit.ly/1bLzr88 only available in source code form. Therefore, you should download the assemblies LINQ to Twitter Source Code, open the LinqToTwitterPcl.sln solution file (requires VS2013), build the code, and create a reference to the LinqToTwitterPcl.dll assembly. You now have a reference to a 3rd party PCL assembly.

In addition to LINQ to Twitter, you need references to the new HttpClient PCL libraries. Therefore, you can either use the assemblies from the LINQ to Twitter download or go to NuGet, by selecting Manage NuGet Packages from the References context menu, type HttpClient into the search box, and Install the Microsoft HTTP Client Libraries. You now have references to Microsoft licensed PCL assemblies.

SNAGHTML16e377cd_thumb

In the future, LINQ to Twitter v3.0 will be available on NuGet and have dependencies on the Microsoft HTTP client libraries, allowing a much smoother experience.

Defining the UI Model

This demo loads tweets into a UITableView. For that, we need a UITableViewSource, which is a Model that holds data that binds to a UI component, the UITableView in this case. The data to bind is a Tweet, shown below:

    public class Tweet
    {
        public ulong StatusID { get; set; }

        public string ScreenName { get; set; }

        public string Text { get; set; }
    }

To keep things simple, this demo just shows ScreenName and Text. We’ll take each instance of Tweet and load it into a set of UITableViewCell instances, which are essentially rows in a table. The TweetTableSource class below, loads Tweet instances into cells to be displayed in a UITableView, which I’ll discuss soon.

    class TwitterTableSource : UITableViewSource
    {
        const string CellIdentifier = "TweetCell";
        readonly List tweets;

        public TwitterTableSource(List tweets)
        {
            this.tweets = tweets;
        }

        public override int RowsInSection(UITableView tableview, int section)
        {
            return tweets.Count;
        }

        public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
        {
            UITableViewCell cell = tableView.DequeueReusableCell(CellIdentifier);
            // if there are no cells to reuse, create a new one
            if (cell == null)
                cell = new UITableViewCell(UITableViewCellStyle.Subtitle, CellIdentifier);
            cell.TextLabel.Text = tweets[indexPath.Row].ScreenName;
            cell.DetailTextLabel.Text = tweets[indexPath.Row].Text;
            return cell;
        }
    }

TwitterTableSource derives from UITableViewSource to work with the UITableView (discussed shortly). The List tweets is a field that both UITableViewSource overrides use. The DequeueReusableCell logic is a way for iOS apps to improve performance and scalability by recycling cells that have scrolled off screen. This demo uses one of the pre-formatted cell types, Subtitle, to set TextLabel and DetailTextLabel with ScreenName and Text, respectively, from the current Tweet instance. The UITableView calls RowsInSection to know how many rows it needs and then calls GetCell that many times, for each Tweet instance. Next, I’ll explain how the UITableView knows to use this TweetTableSource.

MVC in iOS

The pattern used here is Model-View-Controller, where TweetTableSource is the Model, UITableView is the View, and MyViewController is the Controller. The following code, from MyViewController, shows how the controller hooks up the UITableView with the TweetTableSource and establishes UITableView as the View:

Note: This won’t compile yet because I have one more piece of code to discuss after this section.

        UITableView table;

        public override async void ViewDidLoad()
        {
            base.ViewDidLoad();

            table = new UITableView(View.Bounds); // defaults to Plain style
            List tweets = await GetTweetsAsync();
            table.Source = new TwitterTableSource(tweets);
            Add(table);
        }

You would replace fields (e.g. Buttons added in the Hello Application template) with UITableView table and replace ViewDidLoad with the code above. In ViewDidLoad, instantiate a UITableView, get tweets, instantiate a TwitterTableSource, assign the Source property of the UITableView, and add the UITableView instance to the page. The TwitterTableSource is the Model object described in the previous section for loading Tweet instances into rows. The next section shows how to get that collection of Tweet, but notice that tweets is passed to the TwitterTableSource via constructor. By assigning the TwitterTableSource to the Source property of table, the UITableView knows that it can call RowsInSection to learn how many rows it has and then call GetCell to load each of those rows with a Tweet.

Notice how ViewDidLoad is async and GetTweetsAsync is awaited. This is how to load tweets asynchronously, as described in the next section.

An Async Search Query

In this section, we perform the actual Twitter API search using LINQ to Twitter. The important parts of the code are authorization, performing the query, and re-shaping the data. Remember to add a using declarations for System.Threading.Tasks, System.Linq, and LinqToTwitter. Here’s the GetTweetsAsync method that performs this work:

        async Task> GetTweetsAsync()
        {
            var auth = new ApplicationOnlyAuthorizer()
            {
                CredentialStore = new InMemoryCredentialStore
                {
                    ConsumerKey = "",
                    ConsumerSecret = "",
                },
            };
            await auth.AuthorizeAsync();

            var ctx = new TwitterContext(auth);

            var searchResponse = await
                (from search in ctx.Search
                 where search.Query == SearchTerm.Text
                 select search)
                .SingleAsync();

            var tweets =
                (from tweet in searchResponse.Statuses
                 select new Tweet
                 {
                     StatusID = tweet.StatusID,
                     ScreenName = tweet.User.ScreenNameResponse,
                     Text = tweet.Text
                 })
                .ToList();

            return tweets;
        }

The Authorizer used in this example is ApplicationOnlyAuthorizer. Since searches aren’t tied to a specific user, this Authorizer is ideal and gives you a better rate limit. You get your tokens for the CredentialStore by creating a new Twitter app at http://dev.twitter.com. These tokens are your secrets for allowing users to authorize with Twitter, so don’t post them online. Once you’ve initialized the Authorizer, await AuthorizeAsync and LINQ to Twitter will take care of the entire OAuth sequence for you.

Note: Remember to add exception handling logic because authorization errors are a common source of confusion, especially when just starting out with Twitter API programming. For help with authorization errors, please refer to the LINQ to Twitter FAQ.

Next, instantiate a TwitterContext, passing in a reference to the ApplicationOnlyAuthorizer instance. You’re now ready to perform a query.

There are a couple special parts of the query syntax that make it async: await and SingleAsync. The query has a preceding await keyword, which is necessary syntax for async calls. Also notice the SingleAsync operator appended to the query. In addition to SingleAsync, LINQ to Twitter includes SingleOrDefaultAsync, FirstAsync, FirstOrDefaultAsync, and ToListAsync operators. Now you have an async LINQ query for the Twitter API, improving your application’s performance and scalability.

Once the code gets the response back from Twitter, it uses a LINQ to Objects query to re-shape it into Tweet instances. This is the list of tweets passed as an argument to the TweetTableSource constructor, discussed earlier.

That’s all of the code. Now, let’s see it in action.

iTweet

When you run the code, Xamarin.iOS deploys to the Mac and opens the iPhone simulator (make sure you’ve selected iPhoneSimulator in the VS toolbar). The app will automatically do a search and you should see a list of tweets that contain “LINQ to Twitter” in their text. Here’s the program running in the simulator on the Mac:

SNAGHTMLfe6dabb

Summary

Now you know how to use LINQ to Twitter with Xamarin.iOS. You went through several steps to set up the iOS project, define the Model, connect the Model to a View in the Controller, and perform a search query with LINQ to Twitter. Of special note is that you can now work with 3rd party and Microsoft PCL assemblies with ease on multiple platforms, including iOS.

 

@JoeMayo

Posted on Friday, December 6, 2013 8:22 AM LINQ to Twitter , xamarin , iOS | Back to top

Copyright © Joe Mayo | Powered by: GeeksWithBlogs.net