As a .Net developer, I had a lot to learn when I made the jump to developing for iOS. At first I was in awe at how different it was, then later, how much it was the same. All in all it has been a great experience, and today I’m posting some of my thoughts on a few of the adjustments I’ve had to make, and some comparisons between the two. This post will be aimed mostly at C# developers who are learning, or considering learning Objective-C.
Syntax
Switching from the usual dot syntax to Objective-C’s message syntax was probably the single biggest adjustment I had to make. It was like learning a foreign language; at first I had no idea what was going on, then almost all at once I just ‘got it’. I began to enjoy having named parameters as it made the code more readable:
C#
this.eat(porkchop, fork);
Objective-C
[self eat:porkchop withUtensil:fork];
After a while, though, I found that all that verbosity of the messaging syntax didn’t lend it self well to nesting expressions:
C#
this.eat(new ArrayList[]{“Bacon”, “Eggs”}, fork);
Objective-C
[self eat:[NSArray arrayWithObjects:@”Bacon”, @”Eggs”, nil] withUtensil:fork];
This is still a quite readable example; the point is that when you start nesting expressions within the message syntax, you can quickly get lost in square brackets, especially if you are nesting multiple expressions. Obviously using local variables thwarts this (as it is with both languages), but with Objective-C, local variables become a necessity much quicker if you want your code to remain readable.
Memory Management
The second biggest adjustment was not having garbage collection. I miss my garbage collector, but with Objective-C on iOS you get reference counting instead, in the name of performance. This means you have to balance calls to ‘retain’ an object with calls to ‘release’ an object. Too few ‘releases’ and you get a memory leak, too many and you get an EXC_BAD_ACCESS error (crash). Luckily, with Xcode you get a tool called Instruments, which is great for tracking those down. Enabling Zombies, you can find what ‘released’ objects have been messaged, and with Leaks you can find objects the code no longer has a pointer to, but have not
been released (leaked). The biggest task here was learning the rules of object ownership when passing objects around. Luckily Apple has great documentation, and outlines this very well in their ‘Object Ownership and Disposal‘ guide.
Reflection vs. Selectors
Reflection in .Net is a very powerful tool, especially for code that is data-driven. I was pleased to find that doing some reflection-like tasks in Objective-C was even easier. Most of the time I am using reflection to call a method or query a property that, for whatever reason, needs to be dynamic. Since Objective-C already works on the principal of sending messages to objects, the code to dynamically create a message (selector) is very straight forward:
C#:
//Get the type object
Type t = rocket.GetType();
//Get an object representing the method to call
MethodInfo blastoffMethod = t.GetMethod(“blastoff”);
//Use the method object to invoke the method on the object
blastoffMethod.Invoke(rocket, null);
Objective-C:
[rocket performSelector:@selector(blastoff)];
Events vs. Protocols & NSNotificationCenter
In C# you can have events on your objects, each event is declared separately and has it’s own list of listeners. In Objective-C you have protocols, which are like interfaces in #C, that define a set of required and optional callbacks. Listening to an object’s events becomes a matter of implementing the protocol on the ‘listener’ side and setting yourself as the listener, or, ‘delegate’ for that object.
All in all I feel that the delegate & protocol approach is as effective as events in C#, but there’s more! Objective-C has a class called NSNotificationCenter which allows you to broadcast messages into the abyss, for whoever cares to listen. The beauty of this approach is that the listener doesn’t need to know about the sender, or have a reference to it. This is great for tasks that happen in the background that may affect multiple areas of your application (e.g. RSS feed update that triggers a refresh of a screen, and an icon on another screen indicating a new unread message.)
To post a notification is easy:
NSNotification* notification = [NSNotification notificationWithName:@”feedUpdated” object:self];
[[NSNotificationCenter defaultCenter] postNotification:notification];
And adding a listener is equally as easy:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(feedUpdated:) name:@”feedUpdated” object:nil];
Summing up
Those were just a few of the many things I learned when switching languages, and I hope you found it interesting and informative. For those that decide to take the plunge, I would highly recommend taking Stanford’s CS193P course (free!) from iTunes U, and start going through Apple’s great documentation. Happy trails!
One Response
Good post Kyle Kvech. Even I experience the same when switching from.net environment to objective c in IOS. It’s a very different kind of language and added many experience to my programming life 🙂 the features are immense and yes, the IOS documentation is always has a solution for our question. That’s a great resource!