An Introduction to Objective-C for .NET Developers

Over the past year or so I have gone from primarily developing applications using .NET/C# and ASP.NET MVC, to writing iOS applications using Objective-C/Cocoa and using Ruby/Rails for web development.

It’s been an amazing experience, but it can take some time to get used to a new language and platform.

I have found the more languages I learn, the easier it gets to pick up new ones. Many of the core concepts are the same, it’s just a matter of learning the peculiarities of each language/platform (unless you’re learning learning a whole new paradigm, like a functional language).

One thing I find useful when learning a new language is to try and relate certain features back to a language I know and understand. Of course, it’s important to learn the correct conventions for a new language, but that usually happens over time.

For the purpose of this post, I’m going to create a “Document” class in both C# and Objective-C so you can see the differences side-by-side. Let’s start with a quick overview of Objective-C.

What is Objective-C?

Objective-C is the main language used for developing application on Mac OS X and iOS platforms. It is a set of object-oriented classes built on top of C, therefore you can also use C code within an Objective-C Class.

Objective-C is quite different from C#, but there are some similarities. Objective-C isn’t nearly as scary as many people think. Sure, it can be a hassle doing things like manual memory management, but once you understand the patterns, it becomes second-nature. I even think it helps you to consider the lifetime of your objects more and reduce the scope of your objects, which can help improve code design.

Classes

An Objective-C class has both an interface and an implementation. These are usually stored in separate files (ClassName.h for interface, ClassName.m for implementation). The interface defines the instance variables, properties and methods your class has. The implementation is where the methods are implemented. It’s worth noting that an Objective-C interface is not the same as an interface in C# – instead it’s part of the class declaration itself.

Here is an example of a our Document class definition:

C#:

// Document.cs
public class Document
{
    public Document(string title)
    {
        // Initialise properties, etc.
    }
}

Objective-C:

// Document.h
@interface Document : NSObject

- (id)initWithTitle:(NSString *)aTitle;
@end

// Document.m
@implementation Document

- (id)initWithTitle:(NSString *)aTitle {
    if((self = [super init])) {
        // Initialise properties, etc.
    }
    return self;
}
@end

Init methods are used as object constructors. They return an instance of the object. The “id” return type is a dynamic type and can refer to any type of object. We also ensure that the super object has successfully returned a new object before setting any properties.

Objects and Memory

You may have heard that Objective-C requires you to manually manage the memory for objects. This is really not has bad as it sounds. We simply have to be aware of the scope of our objects and “release” them soon as we’ve finished using them.

To create an instance of a class we need to allocate and initialise a block of memory for it on the heap:

C#:

Document document = new Document("My New Document");

Objective-C:

Document *document = [[Document alloc] initWithTitle:@"My New Document"];

If you don’t come from a C background, you may be wondering what the * symbol is all about. Well, this tells us that we’re using a “pointer” to the object. This is similar to reference types in .NET. We refer (or “point”) to the location of that object in memory, not to the object itself. For values types (BOOL, int, etc), we don’t need to use a pointer, as we have a copy of the value itself. For more information here is a good intro to pointers.

Although the Objective-C code above will work, it will cause a memory leak unless we clean up properly. For every object you allocate, you must remember to release that memory afterwards by calling the release method on the object:

Document *document = [[Document alloc] initWithTitle:@"My New Document"];
// Do some stuff...
[document release];

You can also “retain” an object. This is used to ensure an object that was passed to you won’t be cleaned up before you are done using it.

Objective-C uses something called reference counting to handle memory. When you allocate or retain an object, the reference count is increased by one for that object. Each time you release the object, the reference count decreases by one. When a release causes the reference count to reach 0, then dealloc is called and the object is removed from memory.

If you don’t want to manually release an object from memory, you can set it to “autorelease”:

Document *document = [[[Document alloc] initWithTitle:@"My New Document"] autorelease];
// Do some stuff...
// No need to manually release

This is useful when you return an object from a method and you don’t want to burden the caller with releasing the memory for that object. However, autoreleased objects can cause unexpected behaviour, so you should explicitly use “release” whenever possible.

If you are developing an application for Mac OS X you have the option to enable garbage collection. Unfortunately this is not available on iOS. There are some exciting new developments in iOS 5 around memory management, which unfortunately I can’t talk about until the NDA is lifted. Suffice it to say that iOS 5 is going to make all of this a lot easier!

Update: Automatic memory management was introduced in iOS 5 via ARC (Automatic Reference Counting). It’s now possible to write Objective-C code for iOS without the need to retain and release objects. This has made things much simpler and means fewer crashes due to incorrect memory management!

Protocols

Objective-C protocols are similar to .NET interfaces; they specify a list of methods that a class can implement.

In our example the Document class has a Printing protocol in Objective-C and an IPrintable interface in C#. The Printing protocol has a Print method and an optional Preview method. The IPrintable interface only has the Print method, as C# does not allow optional methods on an interface.

C#:

// IPrintable.cs
public interface IPrintable
{
    Print();
}

// Document.cs
public class Document : IPrintable
{
    public void Print()
    {
        Console.WriteLine(@"Printing...{0}", this.Title);
    }
}

Objective-C:

// Printable.h
@protocol Printing <NSObject>

- (void)print;
@optional
- (void)preview;

@end

// Document.h
@interface Document : NSObject<Printing>

@end

// Document.m
@implementation Document

- (void)print {
    NSLog(@"Printing %@", self.title);
}
@end

Methods

Calling methods in Objective-C has quite a different syntax than C#. In fact it took me a while to get used to it. Let’s look an a comparison:

C#:

Document document = new Document();
document.Print();

Objective-C:

Document *document = [[Document alloc] init];
[document print];
[document release];

So that was quite easy. The big difference comes when you need to pass arguments. In Objective-C, the full name of a method includes the names of the arguments:

C#:

public class Document : IPrintable
{
    public bool SaveAs(string fileName, string filePath)
    {
        return true;
    }
}
...
Document document = new Document();
bool success = document.SaveAs("MyFile.txt", "C:\Temp");

Objective-C:

// Document.h
@interface Document : NSObject<Printing>

- (BOOL)saveAs:(NSString *)fileName toPath:(NSString *)filePath;

@end

// Document.m
@implementation Document
...
- (BOOL)saveAs:(NSString *)fileName toLocation:(NSString *)filePath {
    // Add code to save file to path...
    return YES;
}
@end
...
Document *document = [[Document alloc] init];
BOOL success = [document saveAs:@"MyFile.txt" toLocation:@"~/Temp"];
[document release];

So we don’t have a method called “SaveAs” that takes two parameters, instead we have a method called “saveAs:ToLocation:” that includes the two arguments. It’s a bit confusing at first, but gets easier the more you do it.

In Objective-C we usually say we are “sending a message to an object” rather than “calling a method on that object”. In the case above we are sending a print message to our document object. It’s more of a naming convention but it does help you to understand how those messages are handled. For instance you can send a message to a nil object without consequence:

Document *document = nil;
[document print]; // Doesn't cause an error

In .NET however, calling a method on a null object would cause a NullReferenceException.

Properties

Objective-C has properties much like C#. They are declared on the class interface using the @property keyword. The purpose of a property is to encapsulate access to data within an object. This is done using getter and setter methods. We can tell the compiler to create the getter and setter methods for us by using the “synthesize” keyword. This also generates an instance variable that holds the assigned value.

C#:

public class Document : IPrintable
{
    public string Title { get; set; }

    public Document(string title)
    {
        this.Title = title;
    }
}

Objective-C:

// Document.h
@interface Document : NSObject<Printing>

- (id)initWithTitle:(NSString *)aTitle;
@property (nonatomic, copy) NSString *title;

@end

// Document.m
@implementation Document

@synthesize title;

- (id)initWithTitle:(NSString *)aTitle {
    if((self = [super init])) {
        self.title = aTitle;
    }
    return self;
}

- (void)dealloc {
    [title release];
    [super dealloc];
}
@end

The @property declaration defines storage mechanics. In this case we’re saying we want to “copy” the string instead of keeping a pointer to the original. The “nonatomic” keyword means the getter and setter methods that are generated are not thread-safe, but are considerably faster.

Properties are useful because they automatically handle releasing the old object and retaining the new object. Because a property retains the object that is assigned to it, you need to release the property in the dealloc method. It’s also important to ask the superclass to do its cleanup.

Categories

We use Categories in Objective-C to add functionality to a class without the need for inheritance. This behaviour is similar to extension methods in C#. This is useful for adding functionality to classes you don’t own, such as the NSString class.

Here is an example of a category added to the Objective-C NSString class which reverses a string and similar functionality added as an extension method to the .NET System.String class:

C#:

public static class StringExtensions
{
    public static string Reverse(this string s)
    {
        char[] arr = s.ToCharArray();
        Array.Reverse(arr);
        return new string(arr);
    }
};

Objective-C:

// NSString+Reverse.h
@interface NSString (Reverse)

- (NSString *)reverse;

@end

// NSString+Reverse.m
@implementation NSString (Reverse)

- (NSString *)reverse {
    NSMutableString *reversedStr;
    int len = [self length];

    reversedStr = [NSMutableString stringWithCapacity:len];

    while (len > 0)
        [reversedStr appendString:
         [NSString stringWithFormat:@"%C", [self characterAtIndex:--len]]];

    return reversedStr;
}
@end

The “reverse” method now appears on instances of our String classes:

C#:

Document document = new Document("My New Document");
Console.WriteLine(document.title.Reverse());

Objective-C:

#import "NSString+Reverse.h"
...
Document *document = [[Document alloc] initWithTitle:@"My New Document"];
NSLog(@"Reversed title: %@", [document.title reverse]);
[document release];

More information

That was a basic run-down of some core differences between .NET/C# and Objective-C. Here are some useful resources for learning Objective-C:

http://designthencode.com/scratch/
http://cocoadevcentral.com/d/learn_objectivec/
http://www.otierney.net/objective-c.html

If you’d like to know more about Objective-C or iOS development, I’d be happy to continue with some more posts on this topic. Please feel free to post any questions or comments below.

About these ads

6 Responses to “An Introduction to Objective-C for .NET Developers”


  1. 1 mike June 25, 2011 at 10:06 am

    Great article, just what I was looking for, as I struggle to adjust.

  2. 2 steve August 23, 2011 at 6:25 am

    this is very useful. thanks.

  3. 3 dontnetToios March 18, 2012 at 2:20 am

    thanks… useful article

  4. 4 Sadie July 17, 2012 at 11:16 pm

    Really good article! Objective C is really weird at first.

    Have you heard about Josh Smith’s new book? I’ve read the first few chapters and it seems really good.

    http://ijoshsmith.com/ios-for-dotnet-devs/

    Keep the the awesome blog!!

  5. 5 Antonio December 18, 2012 at 8:47 am

    Thanks a lot for this introduction to objective-C for c# developers

  6. 6 liam February 6, 2013 at 6:44 am

    Thanks for this post it is very helpful. It would be very interesting now to hear from you about the memory management changes in ios 5 and how these changes might be of advantage to c# developers that are getting in to objective c. cheers liam


Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s





Follow

Get every new post delivered to your Inbox.

%d bloggers like this: