C# to Objective-C - Part 3 : Classes

Stephen Zaharuk / Wednesday, November 21, 2012

C# to Obj-C: Part 3 – Classes

So far we've taken a look at some basic objects: Strings and Arrays. I think its about time we take the next step and dive into the creation of our own objects! So today I'm going to go over creating custom classes, properties, and methods.  

The first thing to note, is that when you create a new class in objective-c you have 2 files, YourClass.h and YourClass.m. The “.h” file is where you’ll define all of your public methods and properties, where as in the “.m” you’ll have the actual implementation of your class, along with any private fields and methods.

Before we dive right in, lets take a look at the syntax to access properties, fields and methods off of our self and our base class. 

Accessing properties off your object from within your class

C#:
int val = this.Age;

Objective-C:
int val = self.age;

Calling a method off of the base class

C#:
string val = base.ToString();

Objective-C:
NSString* val = [super description];

Access a field

C#:
string name = this._name;
string name = _name;

Objective-C:
NSString* name = self->_name;
NSString* name - _name;

CLASSES:

Every class is broken into 2 parts. The interface, which is the declaration of all the public methods and properties, and the implementation. In C# this isn’t necessary as all your properties and methods have modifiers that determine if it they are private, public or internal.

Person.h
@interface Person : NSObject
-(id)initWithAge:(int)age; // Constructor
@property(nonatomic, retain)NSString* firstName;
@property(nonatomic, retain)NSString* lastName;
@property(nonatomic, readOnly) int age;
-(NSString*)resolveFullName;
@end
Person.m
@interface Person()
{
   int _age; // Private field
}
-(BOOL)validateCanVote; // Private Method
@end

@implementation Person

-(id)initWithAge:(int)age
{
   self = [super init];
   if(self)
   {
      _age = age;
   }
   return self;
}

-(NSString*)resolveFullName
{
   return [NSString stringWithFormat:"%@ %@", self.firstName, self.lastName];
}

-(int)age
{
   return _age;
}

-(BOOL)validateCanVote
{
   return (self->_age >= 18);
}

@end

There is quite a bit going on in the example above. Let me first give you the highlights, and you can read in more detail about methods and properties below in their specific sections.

In the header file, I’m deriving my Person class from NSObject, which is essentially the equivalent of Object in .NET.

Next I’m defining a constructor: initWithAge: And then 3 properties plus 1 method. The 3rd property is readonly.

In the implementation file i start out by declaring the interface again followed by “()” this signifies that I’ve created a private interface and I can define my private fields, methods, and properties here.

Note: you can define your private fields in the header file as well (between 2 curly braces) however, it is no longer recommended that you do that, as its a best practice now to only include public facing API’s in the header.

PROPERTIES:

Although the declaration is a little unfamiliar, properties in obj-c are actually very similar to properties in C#. Lets start out by breaking down the following property declaration:

@property(nonatomic, retain)NSString* firstName;

The first part is quite obvious: @property just means that we’re defining a property.

The next part describes the attributes for this property. Keep in mind that these attributes are only necessary if you’re generating your properties. If you define the properties yourself, they would basically just be there for description.

So what’s the difference between creating a nonatomic vs atomic property?

With “atomic”, the synthesized setter/getter will ensure that a whole value is always returned from the getter or set by the setter, regardless of setter activity on any other thread. That is, if thread A is in the middle of the getter while thread B calls the setter, an actual viable value — an autoreleased object, most likely — will be returned to the caller in A.

In nonatomic, no such guarantees are made. Thus, nonatomic is considerably faster than “atomic”.

Ok, so now what about the second attribute? For a very simple explanation, all you need to know, is that for value types (int, float, CGPoint, etc…) you should use assign. For all reference types, such as custom objects, you should use retain.

After the attributes you have the type of property. In this case its an NSString.

And finally you have name of the property. Note, in obj-c properties should start off with a lower case letter, unlike C# where all properties are uppercase.

So now you have a  brief explanation on defining a property. How about the implementation?

Well, if you are just going to let the compiler generate the property, you’re done. You don’t need to do any thing else. Unless you’re using an older version of xcode (< 4.4) in which case you need to add the following line to your implementation:

@synthesize firstName;

Otherwise if you don’t add this line you’ll get a exception when you access the property at runtime. You can still use @synthesize in xcode  >4.4 , however its no longer a requirement.

In C# the equivalent of @synthesize would be:

public string FirstName{get; set;}

If you wanted to explicitly define the property, you have to add 2 methods to your implementation:

-(NSString*)firstName
{
   return _firstName;
}
-(void)setFirstName:(NSString*)name
{
   _firstName = name;
}

To access your property you have 2 options:

NSString* name = [person firstName];

NSString* name = person.firstName;

To set your property, again, you have 2 options:

[person setFirstName:@"Steve"];

person.firstName = @”Steve”;

Thats right!! You don’t have to use the bracket/message notation with properties, you can use dot notation! See I told you it was pretty similar to C# :)

METHODS:

When I first saw objective-c code, I have to admit it was a little overwhelming. The syntax was just strange, specifically how your create and invoke methods. Although like anything, over time you get used to it, but just starting out its hard to even come up with method names. The platform guidelines state that when you define a method/selector it should read like its a sentence. So each parameter should be part of the sentence that you’re constructing, separated by spaces and colons.

The other strange part is the whole bracket [] syntax. The way it works is the object your calling the method off of should be on the left side of the bracket, and the actual method is on the right side separated by a space.

C#:
this.InvokeMethodWithMultipleParams(“0ne”, 2);


Objective-C:
[self invokeMethodWithFirstParam:@"one" andSecondParam:2];

In the snippet above the obj-c method is actually called: “invokeMethodWithFirstParam: andSecondParam:” Now thats not really a good method name at all and you should never name your methods like this, however its just there to get my point across. The actual declaration for the method above would look like this:

C#:
public void InvokeMethodWithMultipleParams(string p1, int p2){ … }


Objective-C:
-(void) invokeMethodWithFirstParam:(NSString*)p1 andSecondParam:(int)p2;

Now if we wanted the method to be static, we would use a “+” operator instead of a “-” operator at the beginning of the declaration:

C#:
public static void InvokeMethodWithMultipleParams(string p1, int p2){ … }


Objective-C:
+(void) invokeMethodWithFirstParam:(NSString*)p1 andSecondParam:(int)p2;

All methods that you define in your header file would be assumed public, as there is no direct modifier that you would include on your specific method declaration.

And there you go, you now know the basics to dive in and create your own custom objects in objective-c. In my next post I'll explain how to create a protocol aka an interface in objective-c.

In the mean time, if you haven't already, you should check out our brand new iOS product NucliOS. And start writing the next big application today!

You can check out some of the awesome power of the product by checking out our free sample app:

By Stephen Zaharuk (SteveZ)