volperossa
volperossa

Reputation: 1431

Objective C : is bad practice using self as file's owner in init method?

I'm noob in ObjC, I'm trying to understand some basic concept that seems to be confused also in the thousands of tutorial in the web. My problem is with the management of the file's owner. For example, if I want a custom cell in a UITableView object, I need:

1) to make, in Interface Builder, a NIB file with my custom cell
2) create my `CustomCellControllerClass` and set is as Custom Class
   in the Identity Inspector;
3) in my `CustomCellControllerClass` add the IBOutlet property
4) connect every item in my NIB file with respective Outlet 

So, I have in my connection inspector something like this

 item --- File's Owner

Now, begin problems: between all methods proposed, the most "clean" to me seems to be initializing my custom cell in init method in my CustomCellControllerClass ; something like this:

-(id) init
 {
   self=[super init];
   self=[[[NSBundle mainBundle]
        loadNibName:@"CustomCellNib" 
        owner: self options:nil] lastObject];
   return self;
 }

Now, when I start the program all seems ok, but...I can't control the Outlets! I think because I set as Owner an old instance of the self object, loadNibName:Owner:options: returns a new object with owner the old self object. So, the bind between Outlets is made with the old self object. I would that my loaded Nib has owner itself (loadNibName:Owner:options: return CustomCellControllerClass objects, so could not be strange set it as owner of itself), but seems it's not possible.. All this seems to me terribly recursive! The way I found to partially "resolve" the problems is the follow:

-(id) init
 {
   self=[super init];
   CustomCellControllerClass* ccp=[[[NSBundle mainBundle] 
                                  loadNibName:@"CustomCellNib" 
                                  owner: self options:nil] lastObject];
   [self addSubView:ccp];
   return self;
 }

so, I don't lose my original self reference and I can handle my property. The problem is that now my CustomCell is just a subview, with all the problems of the case, I would to make it the "main" view. Is my reasoning right? Where I wrong? How could resolve these problems in a better way?

Upvotes: 0

Views: 91

Answers (1)

Jeffery Thomas
Jeffery Thomas

Reputation: 42598

Registering the NIB with the table view is the correct way to handle this.


To answer your question directly, reassigning self to the first result of -loadNibName:owner:options: is a total kludge! But… sometimes a kludge is what's needed.

As a side note, don't pass self as the owner, pass nil, and use a class method for the NIB name, it will make subclassing easier.

- (instancetype)init
{
    NSBundle *bundle = [NSBundle mainBundle];
    NSString *name = [[self class] nibName];
    self = [bundle loadNibName:name owner:nil options:nil].firstObject;
    return self;
}

+ (NSString *)nibName
{
    return @"CustomCellNib";
}

Here is an updated regarding using self as the owner. In the code sample, you passed self as the owner, then reassigned self to a new object.

-(id) init
 {
   /* old self */self=[super init];
   /* NIB object */self=[[[NSBundle mainBundle]
        loadNibName:@"CustomCellNib" 
        owner: /* old self */self options:nil] lastObject];
   return /* NIB object */self;
 }

As you can see, the owner is the old self, but the returned value is the NIB object. Anything assigned to the owner in the NIB will be assigned to the old self and is lost.


The solution is to never use the owner in the NIB when you have this kind of setup, any outlets you need to setup must be established to the NIB object.

Upvotes: 1

Related Questions