Colin Eberhardt's Technology Adventures

Linq to Objective-C

February 15th, 2013

In the past few months I have been immersing myself into the world of iOS development. Whilst the Objective-C language takes a little getting used to, with its odd syntax and memory management rules, it is certainly a fun platform to develop for. I do miss a few C# language features, such as events, but for the most part I am a happy iOS developer.

… that is apart from Linq!

tree

A few weeks back I was writing some examples for a future release of the ShinobiControls Grid. The example in question required a datasource of people grouped by the first letter of their surname. Despite the use of predicates and key valued sorting, the code looked like this:

- (NSArray*) createGroupedTestData
{
    NSMutableArray* groupedData = [[NSMutableArray alloc] init];
 
    // create some people
    NSArray* people = [PersonDataSource generatePeople:50];
 
    // create a set of letters - based on the first letter of the surname
    NSMutableSet* groups = [[NSMutableSet alloc] init];
    for(PersonDataObject* person in people)
    {
        [groups addObject:[person.surname substringToIndex:1]];
    }
 
    // create the groups
    for(NSString* letter in groups)
    {
        PersonGroup* group = [[PersonGroup alloc] init];
        group.letter = letter;
 
        // locate the person objects that belong in this group
        NSPredicate* predicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
            PersonDataObject* person = (PersonDataObject*)evaluatedObject;
            return [[person.surname substringToIndex:1] isEqualToString:letter];
        }];
        group.items = [people filteredArrayUsingPredicate:predicate];
 
        [groupedData addObject:group];
    }
 
    // sort the groups
    NSSortDescriptor* sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"letter" ascending:YES];
    NSArray* sortedGroupedData = [groupedData sortedArrayUsingDescriptors:@[sortDescriptor]];
 
    return sortedGroupedData;
}

That’s a pretty unwieldy lump in my opinion. With Linq I am used to performing this sort of logic with a single query!

So, I decided to go ahead and implement a bunch of Linq methods for Objective-C, which results in a much cleaner implementation:

- (NSArray*) createGroupedTestData
{
 
    // create some people
    NSArray* people = [PersonDataSource generatePeople:50];
 
    Selector firstLetterOfSurname = ^id(id person){
        return [[person surname] substringToIndex:1];
    };
 
    Selector groupForLetter = ^id(id letter) {
        PersonGroup* group = [[PersonGroup alloc] init];
        group.letter = letter;
        group.items = [people where:^BOOL(id person) {
            return [[[person surname] substringToIndex:1] isEqualToString:letter];
        }];
        return group;
    };
 
    return [[[[people   select:firstLetterOfSurname]
                        sort]
                        distinct]
                        select:groupForLetter];
}

Not only is the above code more concise, which is nearly always a good thing (unless you are talking regex-concise!), it is also much more readable. The ‘select, distinct, sort, select’ query makes it much easier to determine what the resulting output of this code will be.

In this blog post I’ll explain what Linq is (for those of you who have not heard of it before), and how I implemented Linq-to-Objective-C. If you just want to use the code, you can grab a copy from github.

An introduction to Linq

If you are a seasoned .NET developer, you can skip this section, however, if you have not heard of Linq before, then read on …

Linq was added to the C# language back in 2007. The name ’linq’ stands for Language Integrated Query, and as the name implies, its original aim was to more tightly integrate queries into the C# language. As an example, when querying database developers find themselves writing queries using SQL statements embedded within literal strings:

string query = “SELECT * FROM Person WHERE age < 10

The problem with the above code is that the SQL statements are not checked by the compiler, and as a result, errors will only surface at runtime. This is not a problem that is peculiar to C# – you will find SQL statements embedded within strings in virtually every language.

With Linq queries are no longer literal strings, they are instead constructed using keywords that are part of the C# language itself:

var query =  from p in PersonCollection
               where p.age < 10
               select p;

This allows the compiler to check your query syntax, resulting in less error prone code.

C# provides a couple of different syntaxes for Linq, the query syntax, shown above – and the fluent syntax, where method invocations are chained together.

The two are functionally equivalent:

var query =  from p in PersonCollection
               where p.age < 10
               select p;
 
var query = PersonCollection.Where(p => p.age < 10);

Whilst the application of Linq for querying database is obvious, Linq can be used to query practically anything. The .NET framework supplies Linq to SQL, XML and Objects – while the community has added Linq to CSV, JSON, DataSets, Facebook, and my own contribution Linq-to-VisualTree.

I’ve found myself using Linq in virtually every .NET application I have ever written – and I miss it!

Fortunately the ~25 different Linq extensions methods are actually quite easy to implement, as the C# guru Jon Skeet demonstrated in an epic series of blog posts. So, why not bring this API to Objective-C?

Linq to Objective-C

In this section I’ll rattle through the implementation of a number of Linq methods, for the full set, head to github.

Where

The Linq ‘where’ method filters an array of objects based on a predicate that returns true for any object that should be included in the output array. Using a block for the predicate, gives the following method signature:

typedef BOOL (^Predicate)(id);
 
/** Filters a sequence of values based on a predicate.
 
 @param The function to test each source element for a condition.
 @return The elements from the input sequence that satisfy the condition.
 */
- (NSArray*) where:(Predicate)predicate;

Before diving straight into the implementation, I’ll demonstrate its usage via a unit test. Given the following array of Person objects:

- (NSArray*) createTestData
{
    return @[[Person personWithName:@"bob" age:@25],
    [Person personWithName:@"frank" age:@45],
    [Person personWithName:@"ian" age:@35],
    [Person personWithName:@"jim" age:@25],
    [Person personWithName:@"joe" age:@55]];
}

Where Person is a simple object with name and age properties. The test I created for the where method is as follows:

- (void)testWhere
{
    NSArray* input = [self createTestData];
 
    NSArray* peopleWhoAre25 = [input where:^BOOL(id person) {
        return [[person age] isEqualToNumber:@25];
    }];
 
    STAssertEquals(peopleWhoAre25.count, 2U, @"There should have been 2 items returned");
    STAssertEquals([peopleWhoAre25[0] name], @"bob", @"Bob is 25!");
    STAssertEquals([peopleWhoAre25[1] name], @"jim", @"Jim is 25!");
}

Which simply tests that the simple where query successfully returns all Person instances with an age of 25.

The implementation of where is really quite trivial:

- (NSArray *)where:(Predicate)predicate
{
    NSMutableArray* result = [[NSMutableArray alloc] init];
    for(id item in self) {
       if (predicate(item)) {
           [result addObject:item];
       }
    }
    return result;
}

We’re off to a good start!

So, how does this compare to the existing Objective-C APIs? Through the use of predicates it is quite easy to perform the same ‘people who are 25’ query. You can use block syntax:

NSPredicate* predicate = [NSPredicate predicateWithBlock:^BOOL(id person, NSDictionary *bindings) {
    return [[person age] isEqualToNumber:@25];
}];
NSArray* peopleWhoAre25 = [input filteredArrayUsingPredicate:predicate];

Or the more concise string-based predicates:

NSArray* peopleWhoAre25 = [input filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"age=25"]];

With the Objective-C support for predicates, this Linq-style where method might not be the most useful, but the others are more interesting.

Select

The Linq ‘select’ method allows you to perform transformation, which is known as a projection. Each element is acted upon by a selector function, with the returned result being used to populate the output sequence. Here’s the method signature:

typedef id (^Selector)(id);
 
/** Projects each element of a sequence into a new form.
 
 @param selector Projects each element of a sequence into a new form.
 @return An array whose elements are the result of invoking the transform function on each element of source.
 */
- (NSArray*) select:(Selector)selector;

Again, I’ll demonstrate the using via a unit test. This example uses the select method to extract the name property for each person objects in the source array:

- (void)testSelect
{
    NSArray* input = [self createTestData];
 
    NSArray* names = [input select:^id(id person) {
        return [person name];
    }];
 
    STAssertEquals(names.count, 5U, nil);
    // 'spot' check a few values
    STAssertEquals(names[0], @"bob", nil);
    STAssertEquals(names[4], @"joe", nil);
}

Again, the implementation is really quite simple:

- (NSArray *)select:(Selector)selector
{
    NSMutableArray* result = [[NSMutableArray alloc] init];
    for(id item in self) {
        [result addObject:selector(item)];
    }
    return result;
}

Sort

Linq doesn’t actually have a sort method, instead it provides OrderBy and ThenBy methods. Because I don’t want to get into multi-property sorting, I’ll substitute both of these for a single ‘sort’ function.

/** Sorts the elements of a sequence in ascending order.

@return An array whose elements are sorted in ascending order.
*/
- (NSArray*) sort;

/** Sorts the elements of a sequence in ascending order by using a specified keySelector.

@param keySelector A selector that provides the ‘key’ which the array should by sorted by.
@return An array whose elements are sorted in ascending order.
*/
- (NSArray*) sort:(Selector)keySelector;

The first method simply sorts the array by invoking the compare method on each object. The second uses a selector to extract the key that is then used for the comparison.

The unit tests are as follows:

- (void)testSort
{
    NSArray* input = @[@21, @34, @25];
 
    NSArray* sortedInput = [input sort];
 
    STAssertEquals(sortedInput.count, 3U, nil);
    STAssertEqualObjects(sortedInput[0], @21, nil);
    STAssertEqualObjects(sortedInput[1], @25, nil);
    STAssertEqualObjects(sortedInput[2], @34, nil);
}
 
- (void)testSortWithKeySelector
{
    NSArray* input = [self createTestData];
 
    NSArray* sortedByName = [input sort:^id(id person) {
        return [person name];
    }];
 
    STAssertEquals(sortedByName.count, 5U, nil);
    STAssertEquals([sortedByName[0] name], @"bob", nil);
    STAssertEquals([sortedByName[1] name], @"frank", nil);
    STAssertEquals([sortedByName[2] name], @"ian", nil);
    STAssertEquals([sortedByName[3] name], @"jim", nil);
    STAssertEquals([sortedByName[4] name], @"joe", nil);
}

As you can see, one simply sorts an array of NSNumber instances, whereas the other sorts an array of People instances via the name property using the key selector.

The implementation is as follows:

- (NSArray *)sort:(Selector)keySelector
{
    return [self sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
        id valueOne = keySelector(obj1);
        id valueTwo = keySelector(obj2);
        NSComparisonResult result = [valueOne compare:valueTwo];
        return result;
    }];
}
 
- (NSArray *)sort
{
    return [self sort:^id(id item) { return item;} ];
}

The sort-with-keySelector method makes use of the NSArray sort method that sorts via the result returned by a block. The ‘natural’ sort simply uses an identity selector in order to re-use the same implementation.

OfType

The Linq of-type method is use to filter a list of objects to remove all of those which are not of a specific type. Here’s the method signature:

/** Filters the elements of an an array based on a specified type.
 
 @param type The type to filter the elements of the sequence on.
 @return An array whose elements are all of the given type.
 */
- (NSArray*) ofType:(Class)type;

And here is the associated test:

- (void)testOfType
{
    NSArray* mixed = @[@"foo", @25, @"bar", @33];
 
    NSArray* strings = [mixed ofType:[NSString class]];
 
    STAssertEquals(strings.count, 2U, nil);
    STAssertEqualObjects(strings[0], @"foo", nil);
    STAssertEqualObjects(strings[1], @"bar", nil);
}

Which filters out the NSString instances from a mixed array.

The implementation is quite trivial, making use of the where method which was detailed above:

- (NSArray *)ofType:(Class)type
{
    return [self where:^BOOL(id item) {
        return [[item class] isSubclassOfClass:type];
    }];
}

The ofType method is quite useful for tasks such as finding all the subviews of a UIView that are of a specific type.

Distinct

The distinct method returns the distinct elements from an array, in other words, it removes duplicates based on an equality comparison. The signature is as follows:

/** Returns distinct elements from a sequence.
 
 @return An array of distinct elements.
 */
- (NSArray*) distinct;

The unit test is as follows:

- (void)testDistinct
{
    NSArray* names = @[@"bill", @"bob", @"bob", @"brian", @"bob"];
 
    NSArray* distinctNames = [names distinct];
 
    STAssertEquals(distinctNames.count, 3U, nil);
    STAssertEqualObjects(distinctNames[0], @"bill", nil);
    STAssertEqualObjects(distinctNames[1], @"brian", nil);
    STAssertEqualObjects(distinctNames[2], @"bob", nil);
}

The implementation uses an NSMutableArray to construct an array of unique objects:

- (NSArray *)distinct
{
    NSMutableArray* distinctSet = [[NSMutableArray alloc] init];
    for (id item in self) {
        if (![distinctSet containsObject:item]) {
            [distinctSet addObject:item];
        }
    }
    return distinctSet;
}

Note that the use of containsObject on an NSMutableArray is a potential performance issue for large arrays of data. A better method might make use of an NSSet which uses the object’s hash in order to more quickly determine whether an item is already contained within a set.

Select Many

The Linq select-many method is projection where the selector returns an array of objects. The select-many function flattens the returned arrays into a single array. For a good visual explanation of select-many check out this blog post.

Here is the method signature:

/** Projects each element of a sequence to an NSArray and flattens the resulting sequences into one sequence.
 
 @param transform A transform function to apply to each element, this should return an NSArray.
 @return An array whose elements are the result of invoking the one-to-many transform function on each element of the input sequence.
 */
- (NSArray*) selectMany:(Selector)transform;

The unit test takes an array of string, projecting each element to an array via the componentsSeparatedByString method:

- (void)testSelectMany
{
    NSArray* data = @[@"foo, bar", @"fubar"];
 
    NSArray* components = [data selectMany:^id(id string) {
        return [string componentsSeparatedByString:@", "];
    }];
 
    STAssertEquals(components.count, 3U, nil);
    STAssertEqualObjects(components[0], @"foo", nil);
    STAssertEqualObjects(components[1], @"bar", nil);
    STAssertEqualObjects(components[2], @"fubar", nil);
}

A more realistic example might take an array of orders, projecting each order to the order-items that it contains, with the result being all of the order-items over all orders … this could of course be followed by a ‘distinct’ query which would find all the distinct (i.e. unique) items ordered for a collection of orders.

The implementation involves a couple of nested for-in loops:

- (NSArray *)selectMany:(Selector)transform
{
    NSMutableArray* result = [[NSMutableArray alloc] init];
    for(id item in self) {
        for(id child in transform(item)){
            [result addObject:child];
        }
    }
    return result;
}

Aggregate

The next Linq method, aggregate, is an interesting one because it doesn’t return an array, instead it applies an accumulator function to the elements of an array, returning a single result. The signature is as follows:

/** Applies an accumulator function over a sequence.
 
 @param accumulator An accumulator function to be invoked on each element.
 @return The final accumulator value.
 */
- (id) aggregate:(Accumulator)accumulator;

The unit test uses this method to convert an array of strings into a CSV:

- (void)testAggregate
{
    NSArray* names = @[@"bill", @"bob", @"brian"];
 
    id aggregate = [names aggregate:^id(id item, id aggregate) {
        return [NSString stringWithFormat:@"%@, %@", aggregate, item];
    }];
 
    STAssertEqualObjects(aggregate, @"bill, bob, brian", nil);
}

Although you can use aggregate to do all sorts of things, such as find the maximum value for an array of integers.

The implementation is pretty simple, seeding the aggregate with the initial value and using the accumulator for subsequent items:

- (id)aggregate:(Accumulator)accumulator
{
    id aggregate = nil;
    for (id item in self) {
        if (aggregate == nil) {
            aggregate = item;
        } else {
            aggregate = accumulator(item, aggregate);
        }
    }
    return aggregate;
}

A brief note on deferred execution

In C# Linq methods do not act on arrays, instead they act upon the IEnumerable interface. This allows them to query anything that can be enumerated, which not only includes arrays, but can also include infinite sources of data (such as a stream of random numbers). The implementation of Linq relies on the ‘yield’ keyword, which results in the C# compiler creating a state machine to implement the IEnumerable interface.

The practical implication of all this very clever stuff is that Linq queries are not executed immediately. As an example, when you create a query as follows:

var query = PersonCollection.Where(p => p.Age < 10)
                            .OrderBy(p => p.Name);

Nothing will actually happen until you start to enumerate the ‘query’ variable. In other words, you have to ‘pull’ data from the query.

This results in a feature which is often called ‘deferred execution’, where queries are executed on demand. This can yield tremendous performance benefits, allowing queries to terminate early.

Objective-C does not have ‘yield’ keyword, making it hard to implement Linq in such a way as to allow deferred execution. I did actually manage to create an implementation of a few query methods where each were presented as a state machine. Also, the Obj-C for-in iterator uses the NSFastEnumeration, which I was able to implement giving deferred execution and early termination. However, I decided to stick with the much simpler NSArray implementation here. If anyone is interested in the more complex version, give me a shout – I’d be happy to share.

Conclusions

Creating a Linq-style API for Objective-C has proven to be relatively simple (and fun!). I have provided implementations for some of the most common and useful Linq methods, however the .NET Linq APIs for querying collections have a great many more methods than the ones I have covered.

If you are interested, why not pop over to github, fork and add a few more? I’ll probably add to this project myself over time.

Regards, Colin E.

Book Review: iOS Programming for .NET Developers

July 30th, 2012

A couple of weeks ago Josh Smith published his latest book, “iOS Programming for .NET Developers”, which seeks to ease the transition from .NET to iOS developers. As someone who has many years of .NET experience, and more recently a desire to develop for ‘the other side’, I thought this might be the book for me …


Colin Eberhardt is CIO at ShinobiControls, suppliers of highly interactive and fun charts, grid and UI controls for iOS developers.

The technology landscape feels like it is moving faster day-by-day. Tablets and smartphones are becoming ubiquitous, usage of HTML5 is on the rise, whilst Silverlight is unfortunately in decline. The .NET technologies are still a solid foundation for desktop and server-side development, but to deliver cutting edge user-interfaces, you need to add other technologies into the mix. I’ve said it before, but it bears repeating; now, more than ever, is a time for developers to diversify and learn new skills.

Personally I have invested time in learning HTML5 / JavaScript technologies such as Knockout and GWT, but more recently I have been attracted to iOS through my work with ShinobiControls.

For a seasoned .NET developer the transition to JavaScript-based technologies is relatively painless, you can still develop using Visual Studio on a Windows PC. Furthermore, JavaScript is generally quite readable, having a familiar feel to it. In contrast, iOS development is something of a culture shock. It requires a Mac computer, and worse still; Objective-C looks like absolute gibberish! Josh Smith has written a book specifically for those of us trying to make this transition.

So who is this Josh Smith character? I first came across Josh about 5 years ago when I started learning WPF development. Josh was well known for his depth of knowledge, which earned him an MVP award, and the extensive number of articles he wrote on the subject, including his article on the MVVM pattern that became a standard reference on the subject. A couple of years ago he practically disappeared from the Microsoft scene altogether, re-emerging as iJoshSmith (who I like to think of as his robotic alter-ego). Josh spent the next two years learning the art of iOS development – the book he has written is the one he wished had existed when he started on his own personal journey.

Book Format

Before diving into the text itself, we’ll take a quick look at the ‘hardware’. This is a self-published book, with electronic versions available for reading on your Kindle, Nook and iPad. You can also purchase a paperback edition via Lulu. Josh sent me a copy of the paperback, but I also purchased the Kindle edition to see how the two compare. Technical books often have more images, figures and code-samples than text, and eBook versions often fail to reproduce this mixed content well.

The Kindle copy of the book is presented very well and the code samples are quite readable, being reproduced as images in order to maintain the required formatting. Zooming is pretty clumsy on a Kindle, however, almost all of the figures in this book are fine at their default size. Also, this is not a reference guide, so is quite suited to the linear reading style that works well on a Kindle.

The paperback is also good quality; although it feels a little large compared to most technology books. On the plus side, you can quite happily sit it open on your desk as you wrestle with your Mac computer!

Part I: Prepare for Landing

The first chapter looks at why you might want to learn iOS in the first place, from my perspective this is quite obvious! The iPhone and iPad are phenomenally popular devices, and whilst the Android has caught up in terms of market share, the iPhone is still the device that most businesses target first when delivering a mobile application.

A brief overview is given of the alternatives, including Hybrid / HTML5 applications, and MonoTouch, which I have played myself recently. Although, again, the case for native is quite compelling, so Josh wasted very few words here!

The next couple of chapters are all about getting used to the environment, starting with the process of joining the iOS Developer Program and finding your way around a Mac computer. There is an entire chapter dedicated to Xcode. Whilst it is not exhaustive, it does show which parts of the Xcode interface are similar to Visual Studio. The slightly alien looking IDE starts to seem almost familiar after reading this section.

Part II: Ways of the World

The next two chapters are where things start to get serious! Chapter 4 handles moving from C# to Objective-C, while Chapter 5 tackles memory management.

The Objective-C language is introduced by drawing comparisons, where possible, to C#. There are frequent code samples, concerning Ninjas and the odd reference to a The Hitchiker’s Guide. Fortunately I was a Visual C++ developer at one time in my past, so the concepts of separate header and implementation files, and pointers rather than references made sense to me. In other areas, the comparison to C# works well and I certainly feel like I have started to understand the language. However, there are other areas that I feel could have benefited from a little more detail, for example the section on message passing left me wanting to know more, especially about selectors (when do I need to use this oddity?!). Josh does make it clear that this book is not a comprehensive guide to iOS development, and makes frequent reference to other literature (which is typically online and free).

The chapter on memory management details the technique of reference counting, together with the various keywords that manage this process. After reading this chapter a couple of times I feel like I have a good grasp of how to approach memory management on this platform, although I would like to have seen a worked example of memory being incorrectly managed, followed by a diagnosis via instrumentation, and a ‘cure’. Autorelease certainly sounds like an interesting concept, and one that I feel I will need to try for myself to truly appreciate. Josh gives quite a swift overview of Automatic Reference Counting, advising readers to learn how to manage memory manually, advice that I will certainly heed. It is probably all-to-tempting for someone who is used to the Garbage Collector taking the full responsibility for management to reach for something which on the surface of it looks like the iOS equivalent, however it certainly looks like ARC is not a silver-bullet!

The chapters that follow cover the iOS equivalents of the .NET Base Class Library, and how to build user interfaces with Interface Builder. These chapters are all quite easy to follow, demonstrating that iOS has a library of classes, that provide a roughly equivalent set of features to those which we have in the .NET world. The Interface Builder is a tool I have used briefly via MonoTouch, and found it to be very easy to use. These chapters also cover the basic structure of iOS applications and the MVC pattern. These topics are all presented in a concise, yet information rich style.

Part III: Alien Technology

The final few chapters are a mixed-bag, covering other topics that you will most likely encounter during the development of a typical application. There is a good overview of XML, JSON and web services which I must admit I skimmed over – I’ll go back to this section when I need it! Needless to say, it looked no more or less complicated than .NET development, and by this point in reading the book I had almost grown used to the Objective-C syntax and naming conventions!

I found the chapter on Core Data very interested. iOS developers have what looks like quite an advanced object-relation mapping API at their disposal, together with tooling for designing entity models. It was also interesting to see the concept of Key-Value coding, which was introduced in an earlier chapter (and compared to .NET reflection) made use of here.

The final two chapters tackle debugging and unit testing. As expected, Xcode has a pretty similar set of tools to Visual Studio, although there are some ‘instruments’ that related directly to the iOS memory management model.

Summary

iOS Programming for .NET Developers, is a concise, yet information rich guide for .NET developers who are interesting in developing for the iPhone and iPad. What makes this book unique is that it helps you leverage your existing skills in a way that you would find very hard to do by yourself. The similarities between the two environments are far from obvious, but I am happy to say that there are a great many! I feel that reading this book has increased my comprehension of iOS application development far quicker than a standard text on learning iOS would have allowed. This book is also highly sympathetic to the reader who has most likely never used a Mac before, for example, the section on browsing an app’s SQLLite database really ‘holds your hand’ as it leads you through the file system.

I would thoroughly recommend this book to anyone who is starting to learn iOS development. It has certainly helped make the alien landscape feel that little bit more familiar to me.

Regards, Colin E.

An Introduction and Thoughts on Developing iOS Applications with MonoTouch

July 24th, 2012

This blog post describes the creation of a simple twitter search application for iOS, based on a similar application I wrote for Windows Phone a few months back. In this blog post I’ll used the MonoTouch platform, which allows you to write iOS applications using C#. This blog posts describes my experiences, and how it compares to Windows Phone and .NET development in general.


Colin Eberhardt is CIO at ShinobiControls, suppliers of highly interactive and fun charts, grids and UI controls for iOS developers.

With the rise in popularity of smartphones, tablets and the web as a platform, now is the time for developers to diversify and learn new skills. A few years ago, .NET was a dominant force, but recent statistics have shown a real drop in demand for .NET developers. I have been busy picking up new skills, mostly in HTML5-related technologies, but more recently I have been eyeing up iOS as a result of my work with ShinobiControls, which are an iOS UI component vendor.

Whilst the transition from .NET to HTML5 means learning new languages and frameworks, for the most part, the tools (Visual Studio + Windows PC) remain the same. Transitioning from .NET to iOS means that everything changes! There’s a new language, Objective-C, the Cocoa Touch framework, new tools, Xcode, and the Mac OS itself. When learning new skills we tend to gravitate towards the most familiar concepts, these allow us to adapt and use our existing skill. The first time I fired up a Mac, fumbled around to find Xcode, and stared blankly at some Objective-C, I realised there are very few familiar footholds for a .NET developer to leverage when climbing the iOS learning mountain. MonoTouch helps make the transition from .NET to iOS development a little less daunting by allowing you to leverage your existing C# skills.

The Mono framework has had a long history, originally been released in 2004 as an open source implementation of the Microsoft .NET framework. The Mono framework covers many of the core .NET frameworks (ASP.NET, WPF, WinForms), but more recently it has extended its reach to mobile devices, providing an alternative to HTML5 for cross platform mobile application development. Released under the Xamarin banner you can download the tools required to develop C# application for iOS (MonoTouch) and Android (Mono for Android). I originally ‘pigeonholed’ MonoTouch as a technology for cross-platform applications, however, on meeting a number of MonoTouch developers I have found that the majority use this technology simply to leverage their C# and .NET skills for iOS development.

In this blog post I’ll share my impressions of MonoTouch and the first application which I wrote. As a starting point I decided to create an iOS port of the simple Twitter-Search application I developed a few months back to demonstrate the use of the MVVM pattern for Windows Phone development.

From MVVM to MVP

In order to get started with MonoTouch development, you need a Mac, Xcode and MonoDevelop (the graphical IDE for MonoTouch development). You can find information regarding the required tools and where to find them on the Xamarin website.

The Windows Phone twitter search application which I previously wrote uses the Model-View-ViewModel (MVVM) pattern, which is pretty much the de-facto pattern for Windows Phone, Silverlight and WPF development. The first step I took in migrating this application to iOS was to copy the view models into the project that I created via the MonoTouch project template. I was happy to see that these classes, which make use of Linq, Linq-to-XML and various other base-classes compiled immediately!

With an MVVM application the View Model state is kept in synch with the UI via the built-in binding framework. Unfortunately iOS doesn’t have a binding framework, as a result iOS developers do not use the MVVM pattern.

With the MVVM pattern the direction of ‘visibility’ is as follows:

i.e. the View Model is aware of the Model, but the Model is not aware of the View Model. Likewise, the View is aware of the View Model, but not vice-versa. In the absence of a binding framework, you have to manually ‘bind’ the view model to the UI, handling property and collection changes and updating the view accordingly. As an alternative, we give the View Model a reference to the View, allowing it to ‘push’ these changes directly to the view. This change of visibility means that we are no longer using the MVVM pattern, the View Model is now a Presenter as described by the Model View Presenter (MVP) pattern:

I tend to use the pattern where the view for a presenter is declared as an inner-interface of the presenter class (a convention I learnt from using Google Web Toolkit). Properties that would raise PropertyChanged events in a View Model now invoke methods on the View interface to indicate their state change. The View interface can also define events in order to indicate user interactions in place of commands. The complete presenter for my iOS application is given below:

public class TwitterSearchPresenter
{
  /// <summary>
  /// The interface that this presenter depends upon
  /// </summary>
  public interface View
  {
    string SearchText { get; }
 
    void SetIsSearching(bool isSearching);
 
    void SetSearchResults(List<TweetViewModel> results);
 
    event EventHandler StartSearch;
  }
 
  private readonly string _twitterUrl = "http://search.twitter.com/search.atom?rpp=100&&q=";
 
  private View _view;
 
  public TwitterSearchPresenter()
  {
  }
 
  // assocaites this presenter with a view
  public void SetView(View view)
  {
    this._view = view;
 
    // handles events from the view
    view.StartSearch += View_StartSearch;
  }
 
  private void View_StartSearch(object sender, EventArgs e)
  {
    string uri = _twitterUrl + _view.SearchText;
 
    _view.SetIsSearching(true);
 
    WebClient client = new WebClient();
    client.DownloadStringCompleted += Client_SearchComplete;
    client.DownloadStringAsync(new Uri(uri), null);
  }
 
  private void Client_SearchComplete(object sender, DownloadStringCompletedEventArgs e)
  {
    var tweets = ParseXMLResponse(e.Result);
    _view.SetSearchResults(tweets);
    _view.SetIsSearching(false);
  }
 
  /// <summary>
  /// Parses the response from our twitter request, creating a list of TweetViewModel instances
  /// </summary>
  private List<TweetModel> ParseXMLResponse(string xml)
  {
 
    var doc = XDocument.Parse(xml);
    var items = doc.Descendants(AtomConst.Entry)
                      .Select(entryElement => new TweetModel()
                      {
                        Title = entryElement.Descendants(AtomConst.Title).Single().Value,
                        Id = long.Parse(entryElement.Descendants(AtomConst.ID).Single().Value.Split(':')[2]),
                        ProfileImageUrl = entryElement.Descendants(AtomConst.Link).Skip(1).First().Attribute("href").Value,
                        Timestamp = DateTime.Parse(entryElement.Descendants(AtomConst.Published).Single().Value),
                        AuthorId = ExtractTwitterAuthorId(entryElement.Descendants(AtomConst.Name).Single().Value),
                        AuthorName = ExtractTwitterAuthorName(entryElement.Descendants(AtomConst.Name).Single().Value)
                      }
    );
 
    return items.ToList();
  }
 
  private static string ExtractTwitterAuthorId(string name)
  {
    return name.Substring(0, name.IndexOf(" "));
  }
 
  private static string ExtractTwitterAuthorName(string name)
  {
    int bracketIndex = name.IndexOf("(") + 1;
    return name.Substring(bracketIndex, name.Length - bracketIndex - 1);
  }
}

Creating a View

Now that we have a presenter, we need a view!

Windows Phone applications are composed of PhoneApplicationPage instances, the iOS equivalent is a UIViewController. MonoDevelop does not have a built-in editor for view controllers, however, double-clicking the XIB files (which are roughly equivalent to XAML files), launches the Xcode Interface Builder. This tool allows you to create the UI via a simple drag and drop interface. The UI for my application is shown below:

Interface Builder also allows you to wire up controls and their ‘events’ to your Objective-C code, using outlets and actions. The screenshot above shows how I have created outlets for the text-field, activity-indicator and table-view controls, together with an action which is invoked when the search button is pressed.

When you save the view-controller file, MonoDevelop steps in and performs its magic, generating a C# partial class with properties for each outlet and partial methods for actions:

[Register("TwitterSearchViewController")]
partial class TwitterSearchViewController
{
  [Outlet]
  MonoTouch.UIKit.UITextField txtSearch { get; set; }
 
  [Outlet]
  MonoTouch.UIKit.UITableView tweetList { get; set; }
 
  [Outlet]
  MonoTouch.UIKit.UIActivityIndicatorView activityIndicator { get; set; }
 
  [Action("searchButtonPressed:")]
  partial void searchButtonPressed(MonoTouch.Foundation.NSObject sender);
 
  void ReleaseDesignerOutlets()
  {
    ...
  }
}

The net result is that you can wire-up UI controls in much the same way you would using the VS designer.

Your view logic is placed in the associated partial class, in my example this implements the view interface declared by the presenter. It didn’t take me too long to navigate round the API for the various UI controls, using the Xamarin MonoTouch reference as a guide:

public partial class TwitterSearchViewController : UIViewController, TwitterSearchPresenter.View
{
  public TwitterSearchViewController()
    : base("TwitterSearchViewController", null)
  {
    this.Title = "Twitter Search";
  }
 
  ...
 
  public string SearchText
  {
    get
    {
      return txtSearch.Text;
    }
  }
 
  public void SetSearchResults(List<TweetViewModel> results)
  {
    tweetList.Source = new TableSource(NavigationController, results.ToArray());
    tweetList.ReloadData();
  }
 
  public void SetIsSearching(bool isSearching)
  {
    if (isSearching)
    {
      activityIndicator.StartAnimating();
      tweetList.Hidden = true;
    }
    else
    {
      activityIndicator.StopAnimating();
      tweetList.Hidden = false;
    }
  }
 
  partial void searchButtonPressed(NSObject sender)
  {
    // hide the keyboard
    txtSearch.ResignFirstResponder();
 
    // start the search
    OnStartSearch();
  }
 
  public event EventHandler StartSearch;
 
  protected void OnStartSearch()
  {
    if (StartSearch != null)
    {
      StartSearch(this, EventArgs.Empty);
    }
  }
 
  ...
}

Handling the Enter key

When the user taps on the search box, the keyboard is shown. When they hit the enter key we would like to hide the keyboard. This is not the default behaviour for the text field control.

In the .NET world you would expect controls to raise events that you can handle in order to react to user input, for example the TextBox control raises a KeyUp event which could be used to detect an enter key press. The Objective-C approach to this is for UI controls to declare a delegate, which is defined by a protocol. You can supply a delegate to a control and it will be notified of user interactions. For example, the UITextField exposes a UITextFieldDelegate which receives notifications of user interaction.

Protocols are similar to C# interfaces, but with one subtle difference, they can have optional methods. As a result your delegate does not have to handle all of the ‘events’ that a UI control can raise. Unfortunately because C# interfaces cannot have optional methods, it is not possible to map directly from the Objective-C to the C# APIs. MonoTouch solves this by supplying base-classes for each delegate, which implements all the methods defined by a delegate’s protocol. You can sub-class this base implementation so that you just need to add the methods you are interested in.

For example, in order to hide the keyboard on enter key press, we create a delegate implementation and assign it to the UI control as follows:

public override void ViewDidLoad()
{
  base.ViewDidLoad();
 
  txtSearch.Delegate = new CatchEnterDelegate();
}
 
 
public class CatchEnterDelegate : UITextFieldDelegate
{
  public override bool ShouldReturn(UITextField textField)
  {
    textField.ResignFirstResponder();
    return true;
  }
}

This feels like a slightly peculiar pattern for an .NET developer, but it is perfectly workable.

Creating a List of Tweets

For rendering lists of items CocoaTouch provides the UITableView control. This is somewhat equivalent to the Silverlight ItemsControl in terms of where you might use it in your application, however, the API and capabilities are quite different.

In order to render data within a UITableView you must supply a datasource, which is defined by a protocol. MonoTouch again exposes this via a base-class that implements all of the protocol methods, in the case of the UITableView it also combines this with the delegate protocol. The UITableView is virtualised, which means you do not present it with your full set of data, instead you simply inform the table of the number of rows. As the user scrolls the table, the UITableView determines which rows are visible and requests the corresponding cells via the datasource protocol. The UITableView also has a built-in mechanism for re-cycling cells in order to reduce memory usage.

The datasource implementation for the twitter application is shown below:

public void SetSearchResults(List<TweetViewModel> results)
{
  tweetList.Source = new TableSource(NavigationController, results.ToArray());
  tweetList.ReloadData();
}
 
public class TableSource : UITableViewSource
{
  private TweetViewModel[] _tableItems;
  private static readonly string _cellIdentifier = "TableCell";
  private UINavigationController _navigationController;
 
  public TableSource(UINavigationController navigationController, TweetViewModel[] items)
  {
    _tableItems = items;
    _navigationController = navigationController;
  }
 
  public override int RowsInSection(UITableView tableview, int section)
  {
    return _tableItems.Length;
  }
 
  public override UITableViewCell GetCell(UITableView tableView, MonoTouch.Foundation.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);
    }
    var tweet = _tableItems[indexPath.Row];
    cell.TextLabel.Text = tweet.AuthorName;
    cell.DetailTextLabel.Text = tweet.Title;
    cell.Accessory = UITableViewCellAccessory.DisclosureIndicator;
    cell.ImageView.Image = UIImage.LoadFromData(NSData.FromUrl(new NSUrl(tweet.ProfileImageUrl)));
    return cell;
  }
}

The UITableView has a standard cell type which has text, a sub-title, an image and an ‘accessory’ (the item rendered on the right-hand edge) – each of these components is optional.

Again, much of the API was discoverable via the MonoTouch documentation. However, when I wanted to find out how to render an image from a URL the first thing I did was google it, finding the following answer via StackOverflow:

UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:MyURL]]];

It did take a little while to work out how to translate the above to my required C# equivalent:

cell.ImageView.Image = UIImage.LoadFromData(NSData.FromUrl(new NSUrl(tweet.ProfileImageUrl)));

Navigation Structure

So far my discussion of the iOS application has been based on a single view-controller. When the user clicks on a tweet, the application should navigate to a ‘detail’ page:

iOS applications can make use of a UINavigationController, which is similar to the Windows Phone NavigationContext in that it controls the navigation flow of an application, including the back-stack. However, there is a subtle difference, while the NavigationContext is not a UI control, the iOS UINavigationController is responsible for rendering the header-panel and the back-button. This results in a more uniform look and feel for iOS applications and makes it a bit easier to implement basic navigation-based applications.

Using the UINavigationController is simple, you create an instance and set it as your ‘root’ view controller. You can then navigate from one view to the next by ‘pushing’ it:

[Register("AppDelegate")]
public partial class AppDelegate : UIApplicationDelegate
{
  // class-level declarations
  UIWindow window;
 
  public override bool FinishedLaunching(UIApplication app, NSDictionary options)
  {
    // create a new window instance based on the screen size
    window = new UIWindow(UIScreen.MainScreen.Bounds);
 
    // create our presenter and view
    var presenter = new TwitterSearchPresenter();
    var viewController = new TwitterSearchViewController();
    presenter.SetView(viewController);
 
    // create the navigation controller
    var navigationController = new UINavigationController();
    navigationController.PushViewController(viewController, false);
 
    window.RootViewController = navigationController;
 
    // make the window visible
    window.MakeKeyAndVisible();
 
    return true;
  }
}

In order to navigate from a tweet to the detail page, we simply handle the row selection within our table source / delegate:

public class TableSource : UITableViewSource
{
  ...
 
  public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
  {
    var tweet = _tableItems[indexPath.Row];
 
    var controller = new TweetViewController(tweet);
 
    _navigationController.PushViewController(controller, true);
  }
}

Conclusions

Using MonoTouch I was able to implement this simple twitter search application in the space of just a few hours. I have a feeling that if I had tried to use Objective-C, which lacks a garbage collector and a familiar syntax, it would have taken me days rather than hours. For a .NET developer starting out in the world of iOS, MonoTouch certainly helps.
However, by choosing MonoTouch over Objective-C you do make a few compromises, including an increased application size (to include the Mono framework) and the need to generate your own C# bindings for third-party libraries.

Using MonoTouch did allow me to ‘look over the fence’ at what life is like for iOS developers. One thing that immediately struck me was the performance of the UITableView. The WP7 Mango release improved scroll performance, but it is still pretty poor. In contrast the iOS UITableView is lightning fast, regardless of how much data you throw at it.

The iOS APIs also make it much easier to create applications that conform the UI design guidelines. By using the UINavigationController, your applications will have a correctly styled back-button (and will also use the fancy transitions between pages as you navigate between them). The UITableView also has a very useable set of default cell styles.

In conclusion, my feeling is that iOS development requires a bit more effort and the framework is not as ‘rich’ as the Windows Phone Silverlight framework. However, what it does have is speed and consistency. To my mind this is a pretty fair compromise.

I think you’ll see quite a bit more iOS development from me in future!

You can download the code for both the Windows Phone and iOS applications: TwitterSearch.zip

Regards, Colin E.