C# to Objective-C - Part 4 : Interfaces

Interfaces do exist in Objective-C, they just aren’t called interfaces. In fact, if you read my last post on Classes, you probably noticed that in the header file a class was defined as:

@interface MyClass : NSObject

@end

Hmm… if I was coming directly from C# and knew nothing about Obj-C, i’d assume thats the same as .Net interface.  So whats going on above? And whats the equivalent of a C# interface in obj-c?

When you look at the above statement, and you look at it in relationship to the second part of a class declaration, it actually makes a lot of sense.  

@implementation MyClass
@end

So, first we’re defining all the public methods and properties and then we’re implementing all the properties and methods.  So, the interface is the description of your class.

So, now I bet you're wondering, whats the obj-c equivalent called.  It’s  called a “protocol”

@protocol MyInterface
@end

So what if any are the differences between an interface in C# and a protocol in Objective-C?

There actually isn’t much different, except that protocols have a really cool feature. You can mark certain methods as being optional.  What that means is, that you can have a bunch of methods defined on your protocol, and the user does not have to implement them.

@protocol MyInterface
   @required
    -(int)numberOfRowsInView:(MyView*)view;
    -(int)numberOfColumnsInView:(MyView*)view;
   @optional
    -(int)numberOfSectionsInView:(MyView*)view;
@end

Any methods after the @required, will be required by the developer to implement. Anything followed by the @optional, will be strictly optional for the developer to implement.

Ok, so thats pretty cool, and if i’m a developer consuming the interface, thats awesome, I can pick and choose what methods i want to implement. But how does that work if i’me  the developer creating the interface?

Thats a great question, and i’m glad I asked! :)

If i was to write a class that consumes the protocol i designed above, i wouldn’t have to do anything special to consume the required methods.

int rows = [self.myprotocol numberOfRowsInView:self];
int columns = [self.myprotocol numberOfColumnsInView:self];

For the optional method, i need to add an additional line of code before calling selector:

int sections = 1;
if([self.myProtocol respondsToSelector:@selector(numberOfSectionsInView:)])
   sections = [self.myprotocol numberOfSectionsInView:self];

All you basically need to check and see if the method exists on the class you’ve been assigned. If it does “respondToSelector” then you’re good to go, and you can feel free to call it. If it doesn’t, and you try to call the method, you’re going to exception out and your app is going to quit on you.

I just have a couple more things to show you.

To implement an interface on a class, it looks like this:

@interface MyClass : NSObject< MyProtocol1, MyProtocol2 >
@end

Just like in C#, you can assign multiple interfaces to a single class, and just like in C# you separate them by commas. However you need to define all interfaces in “<>”.

And finally, what happens when you want to have a property on your class that is the type of your protocol?

@interace MyClass
@property(nonatomic, weak)id< MyProtocol1 > delegate;
@end

Its important to note, that you should not retain a property that is of type protocol. As it could be any type of object, and you don’t want to  cause a memory leak. B/c of that, if you’re using iOS 5 or above, i actually recommend that you make the property “weak” as opposed to using "assign".  

And if you’re not auto generating the property, make sure that your field is marked as weak:

__weak id< MyProtocol1 > _delegate;

As always I hope this was helpful. Stay tuned for the next post where we'll have some fun with reflection!

By Stephen Zaharuk (SteveZ)


Tags / ,