Jens
Jens

Reputation: 21540

Problem with NSObject init method

I have a problem with the init() method of a standard NSObject. I wrote a class (EFAPersistence) which is a subclass of NSObject. EFAPersistance has a attribute called efaDatabase.

EFAPersistence.h

@interface EFAPersistence : NSObject {
  FMDatabase * efaDatabase;
}

@property (assign) FMDatabase * efaDatabase;

Everytime an instance of EFAPersistance is created I want to assign efaDatabase a value from my AppDelegate.

EFAPersistence.m

@implementation EFAPersistence

@synthesize efaDatabase;

- (id)init {
  if (self = [super init]) {
    efaDatabase = [[NSApp delegate] efaDatabase];
  }
  return self;
}

@end

This way of assigning does not work. But it works if I put the code in a normal method. So I am sure that efaDatabase is correctly instantiated in my AppDelegate. It's just not working in my init() method. That's why I have the feeling that NSApp is not working inside the init() method.

That's how the important AppDelegate code looks like.

AppDelegate.h

@interface AppDelegate : NSObject <NSApplicationDelegate> {
  FMDatabase * efaDatabase;
}

AppDelegate.m

- (id)init {
  if (self = [super init]) {
    NSString * databasePath = 
      [[NSBundle mainBundle] pathForResource:@"efa" ofType:@"sqlite"];

    self.efaDatabase = [FMDatabase databaseWithPath:databasePath];

    if (![efaDatabase open]) {
      NSLog(@"Couldn't open database: %@", databasePath);
      // TODO: Create a database here
    }
    self.db = [[EFAPersistence alloc] init];
  }
  return self;
}

As you can see I am calling the init method. I also affirmed this by using NSLog(). init() is called. The attribute I am trying to assign in EFAPersistence is also created before init() is called.

To sum everything up:

How can I make this work within the init() method so I do not have to write boiler plate code in all my methods of EFAPersistence?

Upvotes: 1

Views: 10807

Answers (2)

Peter Hosey
Peter Hosey

Reputation: 96373

This way of assigning does not work. But it works if I put the code in a normal method. So I am sure that efaDatabase is correctly instantiated in my AppDelegate. It's just not working in my init() method. That's why I have the feeling that NSApp is not working inside the init() method.

NSApp works fine.

Quoting epatel:

I imagine the app delegate is set after the init is done (returned).

Correct. The nib loader completely instantiates each object (including the app delegate, if it's in a nib), then sets it as the value of any properties it's connected to. These are two separate operations; it will not set a not-yet-initialized object as the application delegate.

Quoting you (Jens) again:

The question is how to assign efaDatabase in EFAPersistences only once . There are other methods like awakeFromNib and viewDidLoad etc. But those are not available in a plain NSObject subclass.

Incorrect. awakeFromNib is sent to every object in a nib after the object has been initialized.

That said, I'm curious as to why you have EFAPersistence in a nib. From its name, it doesn't sound interface-related. Shouldn't the app delegate own the EFAPersistence, and the EFAPersistence own the database directly?

Upvotes: 4

epatel
epatel

Reputation: 46051

It looks to me that your AppDelegate is unset when you try to create the EFAPersistance object the first time. This is on below line in AppDelegate.m

self.db = [[EFAPersistence alloc] init];

I imagine the app delegate is set after the init is done (returned).

Upvotes: 4

Related Questions