Init Not Returning Self - objective-c

I have my default initialiser:
- (id)init
{
if ((self = [super init]))
{
}
return self;
}
I have only included this method in my class to track whether it was performing it's job, and from what I can tell, it is.
Self is getting set,and in the console I can see that self has a memory address which is not 0x0000000. For example, here is the console from a run I just tried:
self IssueManager * 0x08383ad0
However, when the method returns self to this method:
- (id)initWithNibName:(NSString *)nibNameOrNil
bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
self.issueManager = [[IssueManager alloc] init];
return self;
}
self.issueManager remains an empty pointer:
_issueManager IssueManager * 0x00000000
I have no idea why this is the case, but would appreciate any help.

Instead of using:
self.issueManager
try:
issueManager = [[IssueManager alloc] init];
Remember, using the dot notation is simply using the accessor/setter methods provided by #property and #synthesize. In your init method, you should not use accessor/setter methods.

I would not use an accessor in -init* (read this: Why shouldn't I use Objective C 2.0 accessors in init/dealloc?)
There is an Apple statement on this as well.
Try to do instead:
_issueManager = [[IssueManager alloc] init];

Related

Xcode 5.1 changes -(id) to -(instancetype) when using built-in init snippet. Why?

How come Apple changed the built-in init method snippet from:
- (id)init
{
self = [super init];
if (self) {
}
return self;
}
to:
- (instancetype)init
{
self = [super init];
if (self) {
}
return self;
}
?
instancetype is the best return type for Objective-C init methods. If you write id instead of instancetype in an init method then the compiler will assume you really meant instancetype (at least in ARC mode).

When overriding `init` method, why it is important to define it again?

I had an exercise to override init method, so I need to create an init method that will set some attributes as well.
My question is: why do I need to define the original init method as well? in case that the new init method won't work?
This is my .h file:
#import <Foundation/Foundation.h>
#import "XYPoint.h"
#interface Rectangle: NSObject
#property float width, height, tx, ty;
-(XYPoint *) origin;
-(void) setOrigin: (XYPoint *) pt;
-(void) translate: (XYPoint *) point;
-(id) initWithWidth:(int) w andHeight:(int) h;
-(id) init;
#end
And .m (only the init methods):
-(id) initWithWidth:(int)w andHeight:(int)h
{
self = [super init];
if (self)
{
[self setWidth:w andHeight:h];
}
return self;
}
-(id) init
{
return [self initWithWidth:0 andHeight:0];
}
I know that it is good this way, but if someone can explain me why is that I would be appreciated.
The idea is to have a central point of initialization for your object instead of sprinkling the initialization of variables throughout each init method.
Your particular example doesn't do much justice to this pattern because you're initializing a Rectangle with 0 width and 0 height, and the default NSObject implementation resets the memory for all instance variables to zero by default, and your initWithWidth:andHeight: method does the same. However, suppose that, you were allocating unit rectangles (width 1, height 1) by default when a Rectangle object was created using,
[[Rectangle alloc] init]
then instead of doing this,
- (id)initWithWidth:(int)width andHeight:(int)height {
self = [super init];
if (self) {
[self setWidth:width andHeight:height];
}
return self;
}
- (id)init {
self = [super init];
if (self) {
[self setWidth:1 andHeight:1];
}
return self.
}
you're centralizing the point of initialization by just doing,
- (id)initWithWidth:(int)width andHeight:(int)height {
self = [super init];
if (self) {
[self setWidth:w andHeight:h];
}
return self;
}
- (id)init {
return [self initWithWidth:1 andHeight:1];
}
This also goes hand in hand with the principle of DRY a.k.a. Don't Repeat Yourself.
This is a trivial example, however, in most real-world objects, you might have a much more complicated setup with notification registration, KVO registration, etc., and then it becomes absolutely crucial that your centralize all that initialization logic.
You don't have do. You generally have one initializer that calls super (self = [super initWithXX]) and the others defer to that one.
In your specific example above its a good idea because initWithWidth:andHeight is acting as the main initializer, so if you call the default what ever code that needs to run in the main initializer will get called.
Btw: Use of the word 'and' in your initializer parameters is a little archaic by modern Objective-C conventions.

Overriding init method to allocate memory for instance variable object

I am attempting to override the init method of a class so that initializing the object also initializes the ivar object:
-(id)init
{
if (self = [super init])
{
someIVarObject = [SomeClass alloc] init];
}
return self;
}
1) Would this code even work, and even so, is this solution discouraged?
2) Why is the if condition not == ? Is it an assignment? If so, why the if?
Sorry if this is obvious! >_<
Yes, it would work, and afaik it's still the way it should be done.
What it does is to call [super init] and allows it to do one of three things;
Return self (ie the same object self is already set to.
Return an entirely new object.
Return nil for failure.
The result is then assigned to self, which makes sure that the rest of the constructor operates on the correct object in case it changed. The if is there to catch the case where [super init] returned nil, in which case the rest of the constructor should be skipped.
1) Here you are declaring a local variable someIVarObject. You should have declared this within the interface or implementation of your class in curly braces, and should then assign it as someIvarObject = .... An example:
#implementation MyClass {
SomeClass *someIvarObject;
}
- (id)init
{
if(self = [super init])
{
someIvarObject = [[SomeClass alloc] init];
}
return self;
}
#end
2) It is an assignment. There is a long history behind this idiom but it mostly comes down to handling the possibility that [super init] returns a different object than init was originally invoked upon.
This...
if(self = [super init])
will work, but it will give you a compiler warning (unless you've turned off this warning).
You can also suppress the warning by using double parenthesis:
if((self = [super init]))
My current preference:
self = [super init];
if(self)
You've got some typos, unbalanced brackets, and the thing you say is an ivar is not an ivar (you declare it inside the if, which makes its scope local to that block. You want to put instance variables in the {}s after your #implementation or #interface declarations). But yes, this is generally how this would work.
However, I'd take a hard look at whether you really need an ivar or not. I can't remember the last time I used one in my code. 99% of the situations I used to use them in, a #property is now a much better solution.
As an added benefit, #propertys synthesize their own getters and setters, (usually) obviating the need to write manual allocing boilerplate, thus making this question moot.
1) this code will work but this line:
SomeClass *someIVarObject = [SomeClass alloc] init];
makes a little sense. Declare SomeClass *someIVarObject in .h file and initialize it in init like this:
someIVarObject = [SomeClass alloc] init];
2) this line if (self = [super init]) is equivalent to:
self = [super init]; if (self != nil)
i.e. it ensures that init method of the base class has returned a proper value

How does initWithNibName work?

I use to create my views programmatically and have started to switch using XIB files. I found this code:
-(id)init
{
self = [super initWithNibName:#"HelpViewController" bundle:nil];
if (self != nil) {
// further initialization needed
}
return self;
}
-(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
NSAssert(NO, #"Initialize with -init");
return nil;
}
It works but why? If I follow the logic, the initWithNibName returns nil and sets it to self. So, self is now nil and then you return self at the end of init. Well, that means you return self which is nil. Is that right?
Also, if I wanted to initialize a NSArray, where should I put it in that init function?
Thanks for the explanation.
Yko
Because the init method calls the self = [super initWithNibName...]. So You must call the init method to create the object. If you use initWithNibName it will fails
For Array you should initialize in init method
-(id)init
{
self = [super initWithNibName:#"HelpViewController" bundle:nil];
if (self != nil) {
// further initialization needed
myArray = [[NSMutableArray alloc] init];
}
return self;
}
You're looking at two different initWithNibName functions.
-(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
NSAssert(NO, #"Initialize with -init");
return nil;
}
The above function is overriding the superclass version of initWithNibName. It raises an assertion informing the caller to use init.
self = [super initWithNibName:#"HelpViewController" bundle:nil];
The above line is calling the superclass version of initWithNibName, which returns a view controller.
If you wanted to initialize an array, you would initialize it where the "further initialization needed" comment is.
It works because you are calling -initWithNibName:bundle: on super (most likely UIViewController), rather than on self (your subclass of UIViewController). If you were to call initWithNibName:bundle on self, then you would hit the assertion or return nil if you have disabled assertions. The superclass implementation of -initWithNibName:bundle: is not affected by your implementation and therefore continues to behave as it normally would.

in objective-c, is if(self) { [self initFOO] } redundant?

I am studying from the Stanford CS193P from Paul Hegarty. Then I see something like this, which I also see other people using:
- (id)init
{
self = [super init];
if (self) {
[self someSetupFunctions];
}
return self;
}
Isn't that redundant? Why not just use:
- (id)init
{
self = [super init];
[self someSetupFunctions];
return self;
}
I thought that messages to nil just fizzle, so why not use this second format?
You may want to do other things than passing messages to self. For example:
- (id)init
{
self = [super init];
if (self) {
// set up ivars
_anIvar = 5;
}
return self;
}
What's really meant by [self someSetupFunctions] is some initialization code, not just a single method call, and a number of important things will fail if self is nil. Most notably, attempting to assign initial values to instance variables will crash.
The self = [super init]; if (self) test is because some initialisers will return different objects, including nil if it's impossible to create an object that satisfies the condition required by the initialiser.
In your own initialiser you need to defend against the superclass doing that, because if you try to access an instance variable on nil you're definitely doing the wrong thing (whether it crashes as a result or not: it usually will).