iosobjective-cdatasourceawakefromnib

Call DataSource method in awakeFromNib


So the question is like this:

I subclass 2 classes, which is UIView(name: Menu) and UIViewController(name: MainController). In Menu, i used xib file to create it layout. In MainController, i added Menu as subview like this and comform to protocol in Menu.

SliderMenu *sliderMenu = [[[NSBundle mainBundle] loadNibNamed:@"SliderMenu" owner:self options:nil] objectAtIndex:0];
sliderMenu.datasource = self;
sliderMenu.delegate = self;
[self.view addSubview:sliderMenu];

The layout works perfectly, there is no problem with it.

The problem is with DataSource. i call a datasource method in awakeFromNib

- (void)awakeFromNib {
// Alloc data
self.data = [[NSArray alloc] initWithArray:[self.datasource arrayOfData]];
}

and that never even get called. After trying and trying i found out that, sliderMenu.datasource = self;is run after awakeFromNib. Thats is why the datasource method in MainController is never get called.

Question: How can i solve this problem?


Solution

  • If you put a breakpoint in -awakeFromNib method, you'll see that this method executes as it should. The thing is, that this method called before datasource assignment, and at this moment your self.datasource is nil.
    I suggest you to override the setter of the datasource property and initialize your data there, e.g.

    - (void)setDatasource:(id<YourProtocol>)datasource
    {
        _datasource = datasource;
        self.data = [[NSArray alloc] initWithArray:[datasource arrayOfData]];
    }
    

    OR

    make a public method, say, prepare and do all your initialization there,

    - (void)prepare
    {
        self.data = [[NSArray alloc] initWithArray:[self.datasource arrayOfData]];
    }
    

    and call this method after datasource assignment:

    SliderMenu *sliderMenu = [[[NSBundle mainBundle] loadNibNamed:@"SliderMenu" owner:self options:nil] objectAtIndex:0];
    sliderMenu.datasource = self;
    sliderMenu.delegate = self;
    [sliderMenu prepare];
    [self.view addSubview:sliderMenu];