📜 ⬆️ ⬇️

Objective-C for C # developers

“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 .NET and C # to Cocoa and Objective-C was not without incident, but it was quite interesting and informative. Soon I have to help develop the new platform and other developers of our company. Therefore, I decided to write a series of introductory notes, which I hope will make this transition smoother.


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

Message sending


In general, the approach of sending messages in Objective-C and, as a result, the method of naming methods is a whole philosophy. At Habré, there was already a post that when people see Objective-C methods, people lose their eyes . This article is intended for people trying to shove them back. The easiest way to do this is to see the analogy with something familiar.
Let's see what a method call looks like in Objective-C. In each example, there will be a real equivalent in C #.
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 it was written above, in Objective-C two types of methods are 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 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 chunk of memory to some default parameters. In C #, when you call a constructor, these operations are not logically separated.
It is recommended to use the second approach, since it shows more precisely the mechanism for creating an object (and we should understand what we are doing, right?) And supports the possibility of using different initialization options (we can override the constructor).
[ [ someObject alloc ] initWithTitle : @ "SomeTitle" ] ;

Here is an example of declaring several constructors of the NSString class:
- ( id ) init ;
Returns an initialized NSString object that does not contain characters.
- ( id ) initWithString : ( NSString * ) aString ;
Returns an initialized NSString object by 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 reference counter


When transitioning 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. Here, this approach will not work, without careful work with the application's memory, you will regularly receive "strange" errors.
The reference counter mechanism implements the base for all NSObject objects. The idea is as follows: each object contains a reference count, if the number of links becomes zero, the destructor (dealloc) is called. Never call dealloc yourself!
The counter value is incremented by one when allocating memory for an object (calling the alloc / new method), when creating a copy of the object (copy message), when sending a retain message to the object. 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 him retain messages and then release), sent a release message (reduced the counter by one), the destructor is called.
With the release message, you need to be careful and avoid unnecessary calls, since a repeated call to the object's destructor will drop the program.
It is also possible to get rid of the need to remember that you need to send a release message to the object (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 recorded in the 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 Shivani Khanna "Objective C for C # Developers" report.
Supplement / corrections are welcome.
Thank you for reading the article!

Source: https://habr.com/ru/post/109134/


All Articles