简体   繁体   中英

How to properly code “init” method in Objective-C, prevent “Expression result unused” warning

I was given a main by my professor that I have to make the .h and .m files for in Objective-C using Xcode. I have it almost done but have two warnings that I can't figure out how to get rid of, "Expression result unused". The errors have to do with my init method for making an array of size 100. Here is where the main creates an object and then calls the method I have coded improperly, this part is given from my teacher and I can't change it:

//  main.m
//  ChutesAndLadders

#import <Foundation/Foundation.h>
#import "ChutesAndLadders.h"
int main(int argc, const char * argv[])
{   
    @autoreleasepool {

        ChutesAndLadders *cl = [[ChutesAndLadders alloc]init];
        [cl initBoard];
        [cl makeChutes:10];
        [cl makeLadders:10];

        int chutes=0; 
        int ladders=0;

        for(int i=0;i<cl.board.count;i++){
            NSString * cell = (NSString *)[cl.board objectAtIndex:i];
            int additionalSpaces = (int)[cl addToMove:cell];
            if(additionalSpaces>0)
                ladders++;
            else if (additionalSpaces<0)
                chutes++;
        }
        [cl printBoard];
    }
    return 0;
}

Here is relevant parts of my method: The error is from the "initBoard" method above, and "initWithCapacity" line below. I know that the two warnings are describing the same error. The code below is mine so I can change it, unlike above.

@synthesize board = _board;

-(id) initBoard
    if((self = [super init]){
        [board intiWithCapacity: 100];
        for(int i = 0; i < 100; i++){
            [board addObject:@""];       
        }
    }
return self;
}

and here is the relevant code from my declaration of "board" in the .h file:

@interface ChutesAndLadders : NSObject{
    @private

    NSMutableArray * board;
}
@property (readwrite, retain) NSMutableArray *board;

-(id) initBoard;

I have tried a lot of small changes in syntax but to no avail. Please don't tell me the solution directly , but a nudge or a shove in the right direction I think is all I need and I will post the solution once I figure get it.

Pseudo solution:

@synthesize board=board;

-(void) initBoard{
    _board = [board initWithCapacity: 100];
    for(int i =0; i < 100; i++){
        [_board addObject:@""];
    }
}

This eliminated one of the warnings, but my program is not running properly so I still have work to do in other methods. This specific question as been addressed though and I have a better understanding of how this is working now.

Actual Solution

@synthesize board=_board;

-(void) initBoard{
    _board = [NSMutableArray arrayWithCapacity:100];
    for(int i =0; i < 100; i++){
        [_board addObject:@"   "];
    }
}

This is the one that finally worked per Hermann . I swear that I tried this once and it didn't work, so I kept playing around and changing things(messing it up more) and then eventually got back to this and it of course worked. Xcode lies sometimes I think to irritate me.

Edit because at first I overlooked something:

Simply use:

ChutesAndLadders *cl = [[ChutesAndLadders alloc]initBoard];

because within initBoard you are calling [super init] anyway.

Does your professor try to trick you? It is difficult to say without having a look at all of the code. You are synthesizing a property board which has the iVar _board. Meaning you can access it's getter or setter respectively by self.board or [self board] or [self setBoard: ...] .

But within the initBoard method it is accessed differently:

[board intiWithCapacity: 100];

Despite the fact that we do not see where board is actually allocated and that the result of the initWithCapacity method is not used, I am asking myself what board actually is. It is not the property (that would be self.board etc) nor is it the iVar (that would be _board ). Apparently just board refers to the private iVar that you declared. But

@synthesize board = _board;

creates an iVar with the name _board of the same type (NSMutableArray*). Therefore in your method, board is different from _board .

Althoug I am editing this for the 3rd time now, I am still not getting it. The .m file was given by the teacher and you have to create a matching .h file, right? In that case you should go for

@private
NSMutableArray * _board;

Well, that is done automatically anyway but writing it with "_" would avoid the creation of a similar named iVar and therefore avoid likely errors.

Background AFAIK: Theoretically or even practically init may create a different instance than the one that alloc created. Therefore you should always use the return value of init.

In general - independent from the strange objective-c notation around object initialization - when ever a method returns a value, then

[object method];

is syntactically correct, runs fine and everything but the return value is unused. And that is what your warning message is all about. Even if you assign it to a dummy object like

SomeClass *someObject = [object method];

you would get the warning that `someClass' is an unused variable.

Last edit: You are nearly there. However, this is a shortcut for current versions of Obj-C, not for older ones: .h file:

@interface ChutesAndLadders : NSObject

@property (readwrite, retain) NSMutableArray *board;

-(void) initBoard;
@end

.m file:

// omitting @synthesize forces the compiler to autosynthesize. In that case it is named "_board"

    -(void) initBoard
        _board = [NSMutableArray arrayWithCapacity: 100]; // this implies the alloc
        for(int i = 0; i < 100; i++){
            [_board addObject:@""];       
        }
    }

You're returning something that you're not using. Also read up on writing proper constructors/initializing objects in Objective-C.

As Hermann said you should do

ChutesAndLadders *cl = [[ChutesAndLadders alloc]initBoard];

and then in your initBoard method

self.board = [NSMutableArray alloc] intiWithCapacity: 100];

You are not following standard Objective-C conventions, and that gets you trapped.

You have an instance variable board. Objective-C convention is that all instance variables should start with an underscore character.

You have a property board, and @synthesize board = _board. The synthesize creates an instance variable with an underscore character, named _board. Now you have two instance variables: board and _board. One of them, _board, is the instance variable backing the board property. The other, board, has nothing to do with board property at all.

And then somewhere you have a harmless looking but fatal statement board = whatever. Which assigns to that totally useless instance variable board. Not _board, but board. If you wrote _board then you would be following Objective-C conventions: Assignment to instance variable using highly visible name. or self.board which would be the property.

And [board initWithCapacity:100] doesn't do anything. First, because the board instance variable (totally unrelated to board property or _board instance variable) hasn't been allocated. It's nil. Sending initWithCapacity to nil does nothing. Sending addObject to nil does nothing either.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM