Chris's coding blog

Objective C by example for a C# developer

June 22, 2009

This is a small set of code snippets that may assist as a quick reference when switching between C# and Objective-C concepts. It’s all beginner level and I’ve skipped some major concepts that a book will explain, as well as any C related tasks.

Update
Thanks to Bill Bumgarner from Apple for his corrections and feedback. In particular alloc and init, autorelease, abstract classes and the constructor sections have been changed.

Update 2
Since I wrote this article I’ve shifted from battling with objective-c to using Monotouch. I’m now maintaining this page of snippets for Monotouch.

Object creation

-int main(int argc, const char *argv[] )
{
// This is the long hand way of doing it.
MyObject *myobj = [MyObject alloc];
[myobj init];
// Bill: Never split the alloc and init calls:
// alloc may return a placeholder that is replaced by -init. Example; NSString never returns a real instance on +alloc
// because it isn't until the -init that it has enough information to know which subclass to use.
MyObject *myobj2 = [[MyObject alloc] init];
// Make sure you release after usage, particularly on the itouch/iphone which has no GC.
// Going into memory management is too big a topic to cover, so it's worth reading up on.
// http://developer.apple.com/mac/library/DOCUMENTATION/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html
[myobj release];
[myobj2 release];
// You can use [myobj autorelease] which will manage releasing retained objects.
// I've ignored reference counting and retaining though, it fits under memory management which you
// will need to read up on if you don't want to make a leaky app.
}
//
// Constructors - Objective-C doesn't have them.
// You can sort of simulate them with initWithName but it won't be the same. As you can see it's a method (which is really
// what constructors are in C# but with special super powers).
// You could use the initializer like so:
// MyClass *myclass = [[MyClass alloc] initWithName: @"hello world"];
//
-(MyClass*) initWithName : (NSString*) aName
{
// This also demonstrates the self and super keywords briefly
self = [super init];
// Bill: Note that some will claim that self.name = name is wrong; you shouldn't use accessors in initializer. I don't happen to agree.
if (self)
self.name = aName;
return self;
}
// Abstract class
// There is no built in language keyword for this, however it's easy to implement
// by overriding the default init method, returning null
- (id)init
{
// You can use NULL or nil
if ([self isMemberOfClass: [AbstractClass class]])
{
NSLog(@"You can't instantiate an abstract class");
[self release];
return NULL;
}
if(self = [super init])
{
// Initialize other stuff
}
// You would also need to do this for methods if you wanted to simulate abstract methods
[self release];
return NULL;
}
view raw gistfile1.m hosted with ❤ by GitHub

The import keyword

There’s two ways of importing, just as with C/C++. The one you want to care about most of the time is in quotes. The angled brackets approach forces the preprocessor to look for the file in the system header directory.

#import <Foundation/Foundation.h>
#import "MyClass.h"

Naming conventions

Objective-C is much like Java and uses Pascal case for classes, and camel case for methods and properties. The link at the bottom page gives more information.

Reflection equivalent, or typeof/is

As far as I’m aware objective-c has no equivalent to reflection in the framework. However for type checking there are many features built in.

// Checking types
-int main(int argc, const char *argv[] )
{
// There's a lot more examples in the 3rd link at the bottom
MyObject *myobj = [[MyObject alloc] init];
MyObject *myobj2 = [[MyObject alloc] init];
if ([myobj class] == [myobj2 class])
NSLog("The same types");
// Also available are isMemberofClass and various respondsTo options.
if ([myobj isKindOfClass: [MyObject class])
NSLog("myobj is a MyObject");
}
view raw gistfile1.m hosted with ❤ by GitHub

Foundation.h, Cocoa, UIKit and AppKit

Regardless of your application, you will almost always include Foundation.h as an import. This is the base library of classes like NSObject, NSString and so on, much like mscorlib.dll in .NET.

Cocoa is used for Cocoa applications on OS X, however on the iPhone/iTouch this is Cocoa Touch library. AppKit is part of the desktop/netbook Cocoa library, however this is replaced by UIKit on the Touch platform. Confused yet?

Classes, encapsulation

Below shows most features you’ll need to know about, with comments describing what is going on. I’ve arranged it in 2 separate files - the header and implementation file. It’s possible to define a class and implementation in the same file however the standard is to have the interface in a header (.h) file, and the implementation in the source (.m) file.

// This is the header file, "Person.h". The NSCopying is an example of implementing a protocol
@interface Person : NSObject //<NSCopying>;
{
// As with .NET, public for member variables isn`t recommended.
@public
BOOL thisIsWrong;
// Protected is the default for fields
@protected
Address *address;
NSString *title;
NSString *firstname;
NSString *lastname;
BOOL isMale;
// Self-explanatory
@private
// There's various ways of using double/floats.
// This is one of them, akin to a Javascript Number object (e.g. floats and ints).
NSNumber *age;
int ageInDogYears; // n.b. This is not a pointer
NSInteger *ageInCatYears;
// Some other C-based datatypes none of them used
char firstLetter;
double aDouble;
float aFloat;
// Collections - mutables allow you to add to them outside of the constructor.
NSArray *myArray;
NSMutableArray *myMutableArray;
NSMutableDictionary *myDictionary;
}
//
// Properties
//
// @property and @synthesis adds automatic getter and setters to the underlying fields.
// You list the fields you have above, and they are then accessible with dot notation
// with thread-safe getters/setters automatically created for you.
// The @synthesis is required in the @implementation. You access your properties using self-&gt;title
@property BOOL isMale;
@property NSString *title;
@property NSString *firstname;
@property NSString *lastname;
@property Address *address;
// Property options (more detail can be found at the links at the bottom of the page)
// Something a C# developer might find odd with objective-c is that if you subclass a class,
// you can make readonly or getter properties writable.
@property (readonly) BOOL isMale; // getter only
@property (readwrite) *firstname; // readwrite is the default and not required.
// Setter related options
@property (readonly,assign) NSString *title; // assign is the default and not required.
@property (retain) *lastname; // this indicates the property should be retained, incrementing the reference count
@property (copy) *address; // this indicates the object being assigned it copied, using its copy method.
//
// Methods -
// All methods are public, there is no access modifiers. The way to implement
// private methods is to remove the definition in the .h file, so they only
// exist in the implementation. Notice the location of the pointer '*' for definitions.
//
// A '+' indicates a static method
+(void) doVeryLittle;
+(BOOL) isLord : (NSString*) title;
+(NSString*) stringFormatExample : (NSString*) title : (NSString*) firstName;
// A '-' indicates instance methods
-(void) runForAnHour;
-(NSString*) getFullName;
-(NSString*) getNewTitle: (BOOL) isALord : (BOOL) isMale;
//
// Protocols
// Creating a protocol forces subclasses to implement the methods listed unless you mark them as optional.
// They are akin to interfaces however you can only force methods to be implemented. Classes can
// implement protocols from multiple different classes.
//
@protocol MyProtocol
- (int) setFavouriteBand;
@optional
-(int) isMadonnaFan;
@end
@end
//
// Categories
// This is simply a way of grouping methods together in smaller blocks, or categories.
// Other classes can also create new categories for your class, but they cannot add new fields.
//
@interface Person (Music) // The implementation code needs the brackets and category name too
-(void) setFavouriteBand;
-(void) isXFactorFan;
@end
// Implementation for the above
#import "Person.h"
@implementation Person
// To match the @property definitions in 'Person.h'
@synthesize isMale,title,firstname,lastname,address;
// You can also specify the backing field for a property (and override existing properties):
@synthesize title = internalTitle;
// Static variables (private)
// These are declared inside the implementation not the header.
static int serial;
@end
//
// Categories
// Implementing a category
//
@implementation Person (Music)
-(void) setFavouriteBand
{
}
-(void) isXFactorFan;
{
}
@end
view raw gistfile1.m hosted with ❤ by GitHub

Exception handling

-(void) exceptionExample
{
//
// Catching exceptions should be familiar to C# programmers
//
@try
{
}
@catch (NSException *exception)
{
NSLog(@"%@ error occured - %@",[exception name], [exception reason]);
}
@finally
{
// Some clean up code
}
//
// Throwing an exception. Apple says:
// "Instead of exceptions, error objects (NSError) and the Cocoa error-delivery mechanism are the
// recommended way to communicate expected errors in Cocoa applications"
//
NSException* myException = [NSException exceptionWithName:@"FileNotFoundException"
reason:@"File Not Found on System"userInfo:nil];
@throw myException;
// Or..
[NSException raise:@"My reason" format:@"format string here", myobject]
}
view raw gistfile1.m hosted with ❤ by GitHub

String example

-(NSString*) stringExample
{
// You prepend a string with @ to indicate to the objective-c compiler that it's an NSString.
// Release messages (see above) aren't required for these and are ignored.
NSString *result = @"initial";
// Strings are immutable as in .NET, however not interned so the same
// string can exist in two memory locations. There is a subclass of
// NSString called NSMutableString which is akin to a StringBuilder.
result = [result stringByAppendingString:@" test"];
return result;
}
-(NSString*) stringFormatExample : (NSString*) title : (NSString*) firstName
{
// This is the equivalent in C# of 'return firstname + " " + firstName;' or the String.format equivalent
// As far as I know, there is no way of concatenation without using formatting.
// %@ is the string format to print an object, like {0}. The overriden description
// method controls the output for an object, which is demonstrated below.
NSString *result = [NSString stringWithFormat: @"%@ %@",title,firstName];
return result;
}
view raw gistfile1.m hosted with ❤ by GitHub

Documentation

// Documentation.
// The defacto for objective-c is DOxygen, much like C++ and C. Its syntax
// is straight forward, just like .NET you use a triple comment line '///' (or /* */)
// and use various tokens like 'param' and 'return'. These can start with
// a '\' or '@' like javadoc. There's no summary token, you simply start
// with '///' and that is your summary. The documentation goes in the .h.
// There is a good Mac OS X DOxygen GUI that produces HTML for you.
// http://www.codeproject.com/KB/tips/doxysetup.aspx
// http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
// Example:
/// \param title The title of the person
/// \param firstName The person`s firstname
/// \return A new name based on the title and firstName
/// Retrieves a new name based on the provided title and firstname
-(NSString*) exampleDocumentation : (NSString*) title : (NSString*) firstName;
//-------------
-(NSString*) description
{
// This is similar to overriding ToString() in .NET for console/string.format output.
// NSLog displays the description property, which this method is used to retrieve its value - its definition is in NSObject.
// Also available is debugDescription
return @"person class";
}
view raw gistfile1.m hosted with ❤ by GitHub

Collections: Dictionary

-(void) dictionaryExample
{
// NSDictionary exists, but you can`t add/remove items to it once it`s initialised
// NSMutableDictionary inherits from NSDictionary
// More info: http://developer.apple.com/documentation/Cocoa/Conceptual/Collections/Collections.html
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
// This is another way to initialise the dictionary, remember to use nil at the end
// nil is just another definition of NULL
NSMutableDictionary *dictionary2 = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"obj1",@"key1",@"obj2",@"key2",nil];
// Adding keys
[dictionary setObject: @"my object" forKey:@"key"];
[dictionary setObject: @"my object" forKey:@"key2"];
// Getting by a single key
NSLog(@"%@", [dictionary objectForKey:@"key"]);
// Enumerating
for (NSString *key in dictionary)
NSLog(@"key: %@, value: %@", key,[dictionary objectForKey:key]);
// Lookups would be performed using enumeration, there is no IndexOf or equivalent.
// Deleting
[dictionary removeObjectForKey:@"key"];
// Count comes from the base, NSDictionary
NSLog(@"Dictionary count: %i", [dictionary count]);
}
view raw gistfile1.m hosted with ❤ by GitHub

Date formatting

+(NSString*) todaysDate
{
// This is an example of date formatting in objective-c/foundation.
// The DateFormatter performs a role similar to DateTime.ToString, there is
// also a fairly rich API in the NSDate class for doing date comparisons and creating new dates.
NSDate *now = [NSDate date];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"dd MM YYYY"];
NSString *result = [formatter stringFromDate:now];
[formatter release];
return result;
}
view raw gistfile1.m hosted with ❤ by GitHub

Links

csharpiphone

I'm Chris Small, a software engineer working in London. This is my tech blog. Find out more about me via GithubStackoverflowResume