Objective-C for C # Developers

  • Tutorial
“If the only language you know is Java or C #, I don’t think you are a professional programmer - you are like a young carpenter who has worked with only one kind of tree so far.”
Uncle Bob


A few months ago, I started developing applications for the iPhone. Switching from the .NET and C # platforms to Cocoa and Objective-C was not without adventures, but it was quite interesting and informative. Soon I will have to help other developers of our company to develop a new platform. Therefore, I decided to write a series of introductory notes that, I hope, will make this transition smoother.


This article will provide a small set of facts about Objective-C from the point of view of a C # developer.

  • Objective-C is an object-oriented language, an “honest” extension of the C language (a program written in C is a program in Objective-C, which is not always true, for example, for C ++).
    Enough detail about the language was written in a recent Objective-C article from scratch .
  • two files are created to describe the object - the header file with the .h extension and the implementation file with the .m extension
  • Objective-C classes are objects, roughly speaking, the Objective-C class can be represented as an implementation of a factory method pattern with a set of static methods.
  • multiple inheritance, as in C #, is not supported.
  • NSObject is the "analog" of the base class System.Object in .NET.
  • when we write interface in Objective-C, we mean class C #.
  • and what we call interface in C #, in protocol Objective-C we call protocol.
  • Objective-C has two types of methods - class methods (we start declaring them with a "+" sign) and instance methods (a declaration begins with a "-"). Class methods, as you understand, are the same static C # methods.
  • if we want to call an object method, we send him a message about it (Objective-C is a message-oriented language, unlike function-oriented C #).
  • in Objective-C, all methods are public (more precisely, in it there is no separation of methods by access level).
  • in Objective-C, all methods are virtual (that is, any method can be overridden in the derived class).
  • Unfortunately, there is no garbage collector in Objective-C (when programming for iPhone). Instead, a link counting mechanism is used.
  • in order to get the property we are used to, in the header file we use the @property keyword to declare the property, and in the implementation file using @syntesize we generate a getter and setter.
  • #import is using
  • self is a pointer to this
  • super is base
  • id is like an object

Sending messages


In general, the approach of sending messages in Objective-C and, as a result, the method naming method is a whole philosophy. On a habr there was already a post that at the sight of methods of Objective-C at people the eyes drop out . This article is for people trying to shove them back. The easiest way to do this is to see an analogy with something familiar.
Let's see what a method call looks like in Objective-C. In each example, a real analogue in C # will be given.
Method without parameters:
C #:
someString.ToLower ();
Objective-C:
[someString ToLower];

With one parameter:
someString.Equals (anotherString);
[someString isEqualToString: anotherString];

With several options:
someString.EndsWith (anotherString, true, someCulture);
[someString isEndedWithString: anotherString withIgnoreCase: YES andCultureInfo: someCulture];

Attached Messages:
someString.Substring (1) .EndsWith (anotherString.Trim (), true, CultureInfo.CurrentCulture);
[[someString getSubstringStartedAtIndex: 1] isEndedWith: [anotherString Trim] withIgnoreCase: YES andCultureInfo: [CultureInfo getCurrentCulture]];


As described above, there are two kinds of methods in Objective-C - instance methods and class methods. Let's see how they are declared in C # and Objective-C.
Instance Method:
public int sum (int firstNumber, int secondNumber);
- (int) sumOfFirstNumber: (int) firstNumber andSecondNumber: (int) secondNumber;

Class method (or static method in C #):
static int Length (string str);
+ (int) Length: (NSString *) str;


A little bit about designers and destructors


As in C #, we can create an object using the new keyword.
[someObject new];

This method is similar to the following operation.
[[someObject alloc] init];

alloc allocates memory for the object, and init initializes this section of memory with some default parameters. In C #, when calling the constructor, these operations are not logically separated.
It is recommended to use the second approach, since it more accurately shows the mechanism of creating the object (and we should understand what we are doing, right?) And supports the possibility of using various initialization options (we can redefine the constructor).
[[someObject alloc] initWithTitle: @ "SomeTitle"];

Here is an example declaration of several constructors of the NSString class:
- (id) init;
Returns an initialized NSString object that contains no characters.
- (id) initWithString: (NSString *) aString;
Returns an initialized NSString object, copying characters from another NSString object.
- (id) initWithCharacters: (const unichar *) characters length: (NSUInteger) length;
Returns an initialized NSString object containing the specified number of characters from the given character array.

If init is a constructor in Objective-C (or a bunch of alloc + init), then dealloc is a destructor (freeing memory). As in C #, it is called automatically.

And a little about the link counter


When migrating from C #, memory management when developing on Objective-C is one of the most important issues. We (.NET developers) are spoiled in this sense - we are used to the fact that in most cases the garbage collector will do everything for us. This approach will not work here, without careful work with the application’s memory, you will regularly receive “strange” errors.
The link counter mechanism implements the basic NSObject for all objects. The idea is this: each object contains a reference counter; if the number of links becomes equal to zero, a dealloc is called. Never call dealloc yourself!
The counter value increases by one when allocating memory for an object (calling the alloc / new method), when creating a copy of the object (copy message), when sending an object with a retain message. To reduce the counter value by one, you need to send a release message to the object.
The scheme of working with an object is usually this: created (the reference counter increased by one), performed the necessary actions (all interested objects send it retain messages, and then release), sent the message release (reduced the counter by one), the destructor is called.
With the release message, you need to be careful and avoid unnecessary calls, since re-calling the object's destructor will drop the program.
There is also the opportunity to get rid of the need to remember that you need to send an object a release message (sometimes this is due to the fact that the object is returned by the method and we do not know its future fate). This can be done using the autoRelease message and the AutoreleasePool object.
[[[someObject alloc] init] autorelease];

The object is written to AutoreleasePool. That is, the release message will be sent to the object “sometime later”, and until then the object will be in memory. “Sometime later” occurs when a release or drain message is sent to an AutoreleasePool object.

In continuation of the topic, I advise you to look at the recent report by Shivani Khanna "Objective C for C # Developers" .
Addition / corrections are welcome.
Thanks for reading the article!

Also popular now: