cxx6xxc
cxx6xxc

Reputation: 171

How to get an NSArray that is returned from a getter method?

Note: This question has been updated with suggestions supplied in answers below in which to bring a fuller context to the present state of the problem.

You may view complete project files here: https://github.com/cxx6xxc/Skeleton/blob/master/README.md

Conditions

  1. I create an NSArray in an object's init method.

  2. I return the NSArray with it's get method.

Problem

Upon arrival, the NSArray is null.

Creating instance

Attempt 1:

This is my original implementation.

- (id)init:
{
    labels = [NSArray arrayWithObjects:@"Red", @"Green", @"Blue", nil];

    return self;    
}

Attempt 2:

Ismael suggested I wrap it with a sub-classing protocol.

neo suggested I retain the NSArray.

- (id)init:
{
    self = [super init];
    if (self)
    {
        labels = [NSArray arrayWithObjects:@"Red", @"Green", @"Blue", nil];

        [labels retain];
    }
    return self;
}

Attempt 3:

Anoop Vaidya suggested I force ownership with alloc and NSMutableArray:

- (id)init:
{
    self = [super init];
    if (self)
    {
        labels = [[NSMutableArray alloc] initWithObjects:@"Red", @"Green", @"Blue", nil];
    }
    return self;
}

But, when I return the object, despite the different init suggestions cited above...

Returning the object

- (NSArray *)getLabels 
{
    return labels; 
}

...with NSMutableArray...

- (NSMutableArray *)getLabels 
{
    return labels; 
}

... the NSArray getter returns a null object.

Calling the method

int main(void)
{
    id view;
    view = [ZZView alloc];

    id model;
    model = [ZZModel alloc];

    id controller;
    controller = [[ZZController alloc] init: model: view];

    labels = [[controller getModel] getLabels];

    if(labels)
        NSLog(@"allocated");
    else
        NSLog(@"not alloced");

    [view dealloc];
    [model dealloc];
    [controller dealloc];

    return EXIT_SUCCESS;
}

Question

What am I not doing, missing or what am I doing wrong that causes the null return value?

Upvotes: 2

Views: 312

Answers (5)

cxx6xxc
cxx6xxc

Reputation: 171

The init method to model was never called, it is only allocated. Therefore, NSArrray labels doesn't exist, because it is created in the init method.

Upvotes: 0

Ismael
Ismael

Reputation: 3937

init methods need to call some [super init], so you will need to do something like this:

- (id)init
{
    self = [super init];
    if (self) {
        labels = [NSArray arrayWithObjects:@"Red", @"Green", @"Blue", nil];
    }
    return self;    
}

Edit: looking at your git repo, I found

controller = [[ZZController alloc] init: model: view];

I'm not entirely sure how the compiler interprets the empty arguments, but my guess is that it reads them as nil, and therefore your ZZController doesn't have model

Also, you have some messy argument order, the first argument (with text init:) is your model, and your second argument (with text model:) is your view (this according to your - (id)init: (ZZModel*)Model: (ZZView*)View

In order to make it work quickly, you should do

controller = [[ZZController alloc] init:model model:view];

I'm gonna take a (short) leap here and guess you are new to iOS development, so I'll recommend that you read about objc programming, how to write functions, how to send multiple parameters, so on and so forth, and after that, do some refactoring

Cheers!

Upvotes: 2

Anoop Vaidya
Anoop Vaidya

Reputation: 46543

You can do it in this way, hoping in .h you have NSMutableArray *labels; :

- (id)init{
    if (self = [super init]) {
        labels = [[NSMutableArray alloc] initWithObjects:@"Red", @"Green", @"Blue", nil];
    }
    return self;    
}

Upvotes: 0

neo
neo

Reputation: 1298

Assume you are not using ARC nor synthesising variable labels, you need to retain the array,

- (id)init:
{
 labels = [NSArray arrayWithObjects:@"Red", @"Green", @"Blue", nil];

 [labels retain];

 return self;    
}

Also, you need to release it when not using the array to prevent memory leakage.

Upvotes: 0

Gwendal Roué
Gwendal Roué

Reputation: 4044

I suggest you put a breakpoint in both your init and getLabels methods, and check the value of the instance variable that stores the array: you'll see which method does not behave as expected.

Upvotes: 0

Related Questions