iOS 101 for .NET Developers Part 2 of N - Classes

May 3, 2011

If you have never written any C or C++ code, then the syntax for Objective-C will feel extremely foreign at first. If you are familiar with C or C++, then it will only feel moderately foreign. For starters, rather than simply defining the entire class in a single file as you would normally in C# or VB.NET, the convention in Objective-C is to define your class in two files. Your “header” file will have a “.h” extension and will define the members, methods, and properties your class will expose. The actual implementation of those class elements will be in an “implementation” file which will share the same filename but will have a “.m” extension.

Class Variable Scope

Objective-C uses most of the same scope modifiers as .NET. By default, class instance variables are defined as “protected”. Other less common options include declaring variables as public or private. The scope rules for each of these modifiers are the same as their counterparts in .NET. Here is a simple header file for a conference Session class.

@interface Session : NSObject {
    @private // accessible only from instances of this class int myPrivateVariable;
    @protected // accessible from instances of this class or subclasses double myProtectedVariable;
    @public // accessible from instances of this or any other class
    NSString *title;
    NSString *abstract;
    NSString *startTime;
    NSString *endTime;
    @package // only used with 64-bit images - accessible anywhere in the image }
    @property (nonatomic, retain) NSString *title;
    @property (nonatomic, retain) NSString *sessionAbstract; @end

Properties

Instance variables (aka “ivars”) may be encapsulated as properties. You can implement you own “getter” and “setter” methods or you can use the equivalent of .NET’s automatic properties by using the @property keyword in conjunction with the @synthesize keyword in your implementation file. In the code block above, I wrapped the title and sessionAbstract instance variables in properties of the same names. The code block below is from the implementation file for the Session class. I manually implement a getter for the title property by creating an instance method with the same name as the property and have it return the proper type. Setters are implemented similarly, but are named with the word “set” followed by the instance variable name. Alternatively, to avoid writing boilerplate accessor code, you can “synthesize” your properties which will generate the accessors for you based on the modifiers used in conjunction with the @property keyword in the class interface file.

#import "Session.h"
@implementation Session
    -(NSString *)title { return title; }
    -(void)setTitle:(NSString *)sessionTitle {
        [title release]; title = [sessionTitle retain];
    }
    @synthesize sessionAbstract; // getter and setter automatically generated
@end

If you want to make sure you are referencing your instance variables as properties through their accessors, then you must reference them through the “self” object. Otherwise, you will be referencing the instance variable directly and bypassing any code you wrote in the accessor methods.

// bypasses setters and references ivars directly
title = newTitle; sessionAbstract = newAbstract;
// calls setters self.title = newTitle;
self.sessionAbstract = newAbstract;

Methods

Methods are defined for a class by specifying the method signature in the interface file (.h) and the implementation in the implementation file (.m). Each method is prefixed by a “+” or a “-” followed by the return type enclosed in parentheses. Methods prefixed with the “-” are instance methods and may only be called on instantiated objects. Methods prefixed with a “+” are class methods and may be called on the class itself. This is the equivalent of static methods in C# (Shared for you VB.NET folks).

The syntax for defining method parameters can feel awkward at first for those more familiar with .NET languages. Each parameter is defined after a colon in the signature. The first parameter is defined simply as the parameter type and the variable name that will be used to refer to the parameter in the method. Subsequent parameters are given a parameter name followed by a colon and then the type and variable name. The following code defines an instance method named updateSession which accepts two string parameters.

// method signature from the interface file 
(void)updateSession:(NSString *)newTitle newAbstract:(NSString *)newAbstract;
// method implementation from the implementation file 
(void)updateSession:(NSString *)newTitle newAbstract:(NSString *)newAbstract {
    // bypasses setters and references ivars directly
    title = newTitle;
    sessionAbstract = newAbstract;
    // calls setters self.title = newTitle;
    self.sessionAbstract = newAbstract;
}

Methods are called by sending a “message” to an instance of a class. Method calls are enclosed in square brackets and take the following form: [object methodName]. The code block below creates an instance of the Session class and then calls the updateSession method on the new object.

Session *newSession = [[Session alloc] init];
[newSession updateSession:@"iOS 101" newAbstract:@"Learn cool stuff!"];

There is more to learn about classes, but I hope I have shown they are not that different from the classes you use and create in .NET. They are conceptually the same. Both are meant as templates to encapsulate the data and behavior or an object. The biggest difference is in the syntax used to define them.

Author image
About Brice Wilson