views:

349

answers:

4

So, I have a class called MazeCell which is declared in "MazeCell.h"

#import <Foundation/Foundation.h>

enum {
    MazeCellEdgeWall = 0,
    MazeCellEdgeGate = 1,
    MazeCellEdgeExit = 2
};
typedef NSUInteger MazeCellEdge;

@interface MazeCell : NSObject {
    MazeCellEdge left;
    MazeCellEdge right;
    MazeCellEdge down;
    MazeCellEdge up;
    NSUInteger drawCount;
    NSUInteger row;
    NSUInteger column;
}
@property MazeCellEdge left;
@property MazeCellEdge right;
@property MazeCellEdge down;
@property MazeCellEdge up;
@property NSUInteger drawCount;
@property NSUInteger row;
@property NSUInteger column;

- (id)initWithLeft:(MazeCellEdge)newLeft
             right:(MazeCellEdge)newRight
                up:(MazeCellEdge)newUp
              down:(MazeCellEdge)newDown
               row:(NSUInteger)newRow
            column:(NSUInteger)newColumn;
@end

Xcode keeps displaying warnings like "warning: 'MazeView' may not respond to '-left'" for all the methods. The funny thing is that the code runs fine on the simulator, it's just that XCode doesn't know the methods.

I was content to ignore the messages until XCode wouldn't let me use MazeCellEdgeWall because it hadn't been declared earlier (all these warnings and errors are in different classes).

So I was wondering if anyone saw any blatant errors that I may have missed because I'm new to programming in general.


Edit: I didn't originally include the code since it is long, but here is the code giving errors.

Here is "MazeCell.m":

#import "MazeCell.h"

@implementation MazeCell

@synthesize left;
@synthesize right;
@synthesize down;
@synthesize up;
@synthesize drawCount;
@synthesize row;
@synthesize column;

-(id) init {
    if (self = [super init]) {
        right = MazeCellEdgeWall;
        up = MazeCellEdgeWall;
        left = MazeCellEdgeWall;
        down = MazeCellEdgeWall;
        drawCount = 0;
    }
    return self;
}

- (id)initWithLeft:(MazeCellEdge)newLeft
             right:(MazeCellEdge)newRight
                up:(MazeCellEdge)newUp
              down:(MazeCellEdge)newDown
               row:(NSUInteger)newRow
            column:(NSUInteger)newColumn
{
    if (self = [super init]) {
        left = newLeft;
        right = newRight;
        up = newUp;
        down = newDown;
        drawCount = 0;
        row = newRow;
        column = newColumn;
    }
    return self;
}
@end

Here is MazeView.h:

#import "MazeView.h"
#import "MazeCell.h"
#import "NSMutableArray+Stack.h"

#define kCellSidesSize 80.0

@implementation MazeView

@synthesize maze;
@synthesize controller;
@synthesize interfaceOrientation;

- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        interfaceOrientation = UIInterfaceOrientationPortrait;
        [self setBackgroundColor:[UIColor greenColor]];
        [self setUserInteractionEnabled:YES];
        [self setMaze:[[Maze alloc] initWithSize:MazeSizeMake(4, 6)]];
    }
    return self;
}

- (void)setMaze:(Maze *)newMaze {
    maze = newMaze;
    CGRect newFrame = [self frame];
    newFrame.size = CGSizeMake([newMaze size].width * kCellSidesSize,
                               [newMaze size].height * kCellSidesSize);
    [self setFrame:newFrame];
}

- (void)setInterfaceOrientation:(UIInterfaceOrientation)newOrientation {
    if (interfaceOrientation != newOrientation) {
        interfaceOrientation = newOrientation;
        CGRect oldFrame = [self frame];
        [self setFrame:CGRectMake(oldFrame.origin.y, oldFrame.origin.x,
                                  oldFrame.size.height, oldFrame.size.width)];
        [[self superview] setContentSize:[self frame].size];
    }
}

- (void)setController:(UIViewController *)newController {
    if (controller != newController) {
        controller = newController;
    }
}

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    NSUInteger columns = [[self maze] size].width;
    NSUInteger rows = [[self maze] size].height;

    CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);
    CGContextSetLineWidth(context, kCellSidesSize - 2.0);
    CGContextSetLineJoin(context, kCGLineJoinRound);
    CGContextSetLineCap(context, kCGLineCapRound);

    BOOL isDrawing = NO;
    MazeCell *aCell;
    NSMutableArray *aStack = [[NSMutableArray alloc] init];
    NSUInteger row = 0;
    NSUInteger column = 0;

    while (YES) {
        aCell = [maze getCellInRow:row andColumn:column ofOrientation:interfaceOrientation];

        if (isDrawing) {
            CGContextAddLineToPoint(context, row * kCellSidesSize + kCellSidesSize / 2.0,
                                          column * kCellSidesSize + kCellSidesSize / 2.0);
        } else {
            isDrawing = YES;
            CGContextMoveToPoint(context,  row * kCellSidesSize + kCellSidesSize / 2.0,
                                        column * kCellSidesSize + kCellSidesSize / 2.0);
        }

        if ([aCell left] == MazeCellEdgeExit && [aCell drawCount] < 1) {
            //Warnings and errors
            [aCell setDrawCount:1];  //Warning
            column--;
        } else if ([aCell right] == MazeCellEdgeExit && [aCell drawCount] < 2) {
            //Warnings and errors
            [aCell setDrawCount:2];  //Warning
            column++;
        } else if ([aCell up] == MazeCellEdgeExit && [aCell drawCount] < 3) {
            //Warnings and errors
            [aCell setDrawCount:3];  //Warning
            row--;
        } else if ([aCell down] == MazeCellEdgeExit && [aCell drawCount] < 4) {
            //Warnings and errors
            [aCell setDrawCount:4];  //Warning
            row++;
        } else if ([aStack count] > 0) {
            aCell = [aStack pop];
            row = [aCell row];       //Warning
            column = [aCell column]; //Warning
            isDrawing = NO;
        } else {
            break;
        }
    }
    CGContextStrokePath(context);
    [aStack release];
}

@end

Again, this is provided to prove that I have coded things. This program works and, as I said, the maze cell methods actually do work, it's just that Xcode is giving me warnings which I wouldn't care about, except that it says I haven't defined MazeCellEdgeExit and so doesn't compile anymore, but it does compile otherwise.

+1  A: 

You neglect to include the code that's actually generating the warnings, but it sounds like wherever it is, you haven't imported the MazeCell.h header file.

Chuck
A: 

It's possible that the object ('MazeView') you're alloc'ing and init'ing might not be a 'MazeCell' object. This may be caused by neglecting to import the MazeCell.h as Chuck mentioned or your simply creating the 'MazeView' object with the wrong class, maybe as a result of copy and pasting your own code (just a guess, as it seems counter-intuitive to create an object of a MazeCell type and name it 'MazeView').

I also suspect, though don't have access right now to Xcode to test, that your typedef might be declared incorrectly (or I'm simply not familiar with that syntax style). Try replacing your 6 lines of the typedef with this.

typedef enum {
    MazeCellEdgeWall = 0,
    MazeCellEdgeGate = 1,
    MazeCellEdgeExit = 2
} MazeCellEdge;

EDIT: Since you have just included the implementation file, I noticed that it's for MazeView (line 7), but your original header file is for MazeCell. So as of right now, you actually haven't written any code (or not posted any) that is actually for a MazeCell object.

I'm also suspecting that you haven't @synthesize'ed (or written methods for them) any of your instance variables.

Neil Daniels
MazeCell and MazeView are indeed different classes. I simply put #import "MazeCell.h" in the code to demonstrate that I was definitely importing MazeCell.hYour recommendation unfortunately did not work.
Joe
In your MazeView implementation you a Maze object (as in setMaze:(Maze *)newMaze), it appears that it has a method getCellInRow:andColumn:ofOrientation that actually sets aCell to be a MazeCell. I would make sure that what it returns is actually a MazeCell.
Neil Daniels
It does return a MazeCell
Joe
I realize now that the methods might not actually work but give the illusion of doing so by returning a nil object
Joe
+1  A: 

Now this is quite strange. But I have discovered that duplicating the MazeCell.h and MazeCell.m files and renaming them to MzCell.h and MzCell.m, and then replacing every reference to MazeCell with MzCell got this program to run.

Although that opens up more questions than it answers...

Joe
Copying all your classes into a project and compiler and faking an interface for the Maze and MazeView classes (since you didn't provide them), I can say: there are no compiler errors in your code. You probably didn't need to rename these files to fix the error, a straightforward Clean and then Build would likely have fixed it.Compilers sometimes get confused. If there is no obvious cause of a problem, try a Clean and then Build. This will also fix the occasional situation where no error is given when there *should* be an error.
Matt Gallagher
That is curious. Have you looked at the project symbols list in the sidebar of the Xcode project? Is MazeCell defined elsewhere?
Quinn Taylor
+1  A: 

Everything looks good to me. Try a clean and build. It's quite possible that outdated object files are floating around, confusing the compiler or linker.

I haven't been able to detect a bug that would prevent compilation, although there are a number of apparent memory leaks, such as in setMaze: where you don't release the old maze. (You definitely allocate a maze in -initWithFrame: so you leak at least that one.) Also, the default setter semantic is "assign", not "retain" or "copy" — in this case, it would seem that one of the latter two behaviors would make more sense. I realize you're new to Objective-C, so these are meant by way of constructive feedback, not criticism. :-)

Quinn Taylor
While I already have the code working, I imagine that this was the real problem because I did redo the MazeCell file a few times. I didn't realize there was such a thing as Clean and Build. Thank You.
Joe
Not a problem. While the compiler will regenerate file that you change directly, code that you haven't modified may still be compiled against the old version of the modified code (which in your case probably didn't have all those methods declared), hence the warnings. I structure my projects so I can completely delete the `build` folder next to the Xcode project file and everything will be rebuilt cleanly. Glad you've got it working now! :-)
Quinn Taylor

related questions