0

Iam in the first phase of Objective-C learning curve, so please bear with me :).

Iam reading Apple documentation and doing exercises there also. Ive come to a problem with initialization of particular object, because I get unexpected (In my opinion) behavior in my Xcode.

To the point (lets make it simple):

STEP 1:

I have declared simple variable from a my custom class named XYZPerson. It looks like this:

 XYZPerson *randomPerson;

"If" check for initialized object returned out "Not Initialized" (as expected).

if(randomPerson == nil) {
        NSLog(@"Random person is not initialized");
    } else {
        NSLog(@"Random person is  initialized");
    }

STEP 2:

I have allocated the memory for this object using "alloc" word on this variable. As I understand in this phase, memory for this variable gets allocated. It also returns the pointer?

Line of code looks like this:

XYZPerson *randomPerson = [XYZPerson alloc];

Checking for "nil" surprised me: (It executes "else" statement).

if(randomPerson == nil) {  
        NSLog(@"Random person is not initialized");
    } else {
        NSLog(@"Random person is  initialized");  
    }

I can also send messages to this object and they are executed just fine, without calling "init" method.

How can this be? Am I missing something? How can "randomPerson" variable be initialized before calling "init" method on this instance? Why is "init" there in the first place then?

Furthermore, the accepted answer here Difference between ! and nil check on Objective-C object , says that ALL object are set to nil in the alloc method!

Iam coming from Java and there is one way of declaring an object using "new" keyword. Without using "new" the instance of object will be always "null", and calling methods on that instance will result "NULLPOINTEREXPECTION Error".

P.S Is "nil" in objective C, same as "NULL" in Java?

Whole project looks like this:

main method:

 XYZPerson *randomPerson = [XYZPerson alloc];

    if(randomPerson == nil) {

        NSLog(@"Random person is not initialized");

    } else {
        NSLog(@"Random person is  initialized");
    }

**XYZ Person Class:**

    #import "XYZPerson.h"

@implementation XYZPerson

-(void)sayHello {

    //[self saySomething];

}

-(void)saySomething:(NSString *) greeting {

    NSLog(@"%@", greeting);

}



@end
Community
  • 1
  • 1
rootpanthera
  • 2,731
  • 10
  • 33
  • 65

1 Answers1

1

I post an answer additional to that one linked in the comment for two reasons:

A. Your Q is slightly different.

B. I do not confirm with the linked answer in details.

First of all to your additional Qs: Yes, nil is Objectice-C's NULL. But there are some differences:

A. In most cases (using ARC) a reference to a pointer (not the object itself) is initialized with nil.

XYZPerson *person; // Usually automatically set to nil.

B. A message to nil is allowed in Objective-C, does not throw an exception and returns NO, 0, 0.0, nil, or whatever the representation of null resp. zero (if it does not have a null representation like integers) is for that type. Sometimes this is done intentionally and you can rely on that.

Two your main Q:

After creating an instance object with +alloc all instance variable (ivars) are set to NO, 0, 0.0, nil, or whatever the representation of null resp. zero is for that type. You should not set such ivars explicitly to that value.

For example, if the instances of the class XYZPerson has an ivar for the name typed NSString*, the ivar will be nil. So, one might think that an naked -init does not have any meaning, because it does not take parameters and therefore does nothing. But you simply do not know: Maybe something else is done in -init. And, that's probably a surprise for a Java developer, -init returns an object reference, so you cannot know, whether -init replaces the instance object, for example for twin toning. So even you do not see any meaning in it, the first message to an instance object has to be init. (Yes, in many case you would not see any difference, but you do not know, whether there is one or not or will be in future. It is a part of the API contract, so do it.)

In disagree with the linked answer in one point:

Sending +new… instead of +alloc -init is the better way to do it.

A. If you use a simple +new it is correct that it sends +alloc -init in many cases. Therefore it is obvious that this is not better or worse than sending +alloc -init. It is what it does. You always have to have a look at the documentation, whether a naked initialization, using +new or +alloc -init is allowed. But in such a case you likely do not want to do a naked initialization, because it is meaningless.

B. Sometimes it is for the implementor of a class easier to receive a new message to the class object.

Amin Negm-Awad
  • 16,582
  • 3
  • 35
  • 50