I am setting the value of a key in an NSDisctionary using this:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(#"touchesEnded currentcolor: %#", currentColor);
if (currentTool == #"paint") {
NSLog(#"End Paint");
CGPoint point = [[touches anyObject] locationInView:self.view];
MaskPath * myNewPath = [mapView.drawthis containsPoint:point];
[myNewPath.attributes setValue:currentColor forKey:#"fill"];
[mapView setNeedsDisplay];
} else {
NSLog(#"End Pattern");
currentColor = #"1.png";
CGPoint point = [[touches anyObject] locationInView:self.view];
MaskPath * myNewPath = [mapView.drawthis containsPoint:point];
[myNewPath.attributes setValue:currentColor forKey:#"fill"];
[mapView setNeedsDisplay];
}
}
If I try to log the value of currentColor the app crashes with exc bad access (line 3)
If I take the Log out and go with the hardcoded value everything works fine. It also works fine with the first part of the if statement. I've checked the function that assigns currentColor and it is delivering the correct values. If I hard code the value of currentColor at that point it works fine. I've run the analyzer and I've got no memory leaks or issues. How else can I track this issue down?
One glaring issue is that you are working with an autorelease variable as evidenced by your example. Most likely you are doing the same thing outside of that method.
I recommend you make currentColor a property:
#property (nonatomic, retain) NSString *currentColor;
Then, to set it, you would do something like this:
self.currentColor = #"SomeColor";
Since you declared the currentColor property with a retain, you will not get a bad access when you pass it to your NSLog:
NSLog(#"This is my color: %#", self.currentColor);
If you already DO have a currentColor property and you are simply assigning the ivar, then you should be doing:
currentColor = [NSString alloc] initWithString:#"Foo"];
To sum it up:
1. self.currentColor = #"Foo"; //<-This is automagically retained
2. currentColor = [NSString alloc] initWithString:#"Foo"]; //<-Accessing the ivar directly, so you must ownify the string :D
Related
I am new to this so it may be that I'm missing something simple or whatever else.
Basically I want to draw a straight line from point to point, in my case I have all of my points in which each line should be drawn in an array of coordinates. And then I use overlay method to draw the line. And all of this in a MKMapView which I already defined and configured (Correctly).
So here is the code that I use to fill my array of coordinates and also create the overlay/polyline:
CLLocationCoordinate2D coordinateArray[arrayOfLatitudes.count];
for (int i = 0; i < arrayOfLatitudes.count; i++) {
double tempLatitude = [[arrayOfLatitudes objectAtIndex:(i)] doubleValue];
double tempLongitude = [[arrayOfLongitudes objectAtIndex:(i)] doubleValue];
coordinateArray[i] = CLLocationCoordinate2DMake(tempLatitude, tempLongitude);
}
self.routeLine = [MKPolyline polylineWithCoordinates:coordinateArray count:arrayOfLatitudes.count];
[self.mapView setVisibleMapRect:[self.routeLine boundingMapRect]]; //If you want the route to be visible
[self.mapView addOverlay:self.routeLine];
and this is my ViewForOverlay method which I asume configures my routeLine:
(MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
{
if ([overlay isKindOfClass:[MKPolyline class]])
{
MKPolylineView *mapOverlayView = [[MKPolylineView alloc] initWithPolyline:overlay];
//add autorelease if not using ARC
mapOverlayView.strokeColor = [UIColor redColor];
mapOverlayView.lineWidth = 3;
return mapOverlayView;
}
return nil;
}
I have these declarations in my .h as well:
#property (nonatomic, retain) MKPolyline *routeLine;
#property (nonatomic, retain) MKPolylineView *routeLineView;
I don't know why I can't see my routeLine drawn in my MapView, because I have used the exact logic(order of things) in another class and the lines appear with no problem.
What am I missing here? please help me
thanks in advance
I forgot to mention,The first block of code is inside a method called "waitForMe" (void). Im calling waitForMe from my viewDidLoad method.
First of all, I'm an Objective-C novice. So I'm not very familiar with OS X or iOS development. My experience is mostly in Java.
I'm creating an agent-based modeling-framework. I'd like to display the simulations and to do that I'm writing a little application. First, a little bit about the framework. The framework has a World class, in which there is a start method, which iterates over all agents and has them perform their tasks. At the end of one "step" of the world (i.e., after all the agents have done their thing), the start method calls the intercept method of an object that implements InterceptorProtocol. This object was previously passed in via the constructor. Using the interceptor, anyone can get a hook into the state of the world. This is useful for logging, or in the scenario that I'm trying to accomplish: displaying the information in a graphical manner. The call to intercept is synchronous.
Now as far as the GUI app is concerned, it is pretty simple. I have a controller that initializes a custom view. This custom view also implements InterceptorProtocol so that it can listen in, to what happens in the world. I create a World object and pass in the view as an interceptor. The view maintains a reference to the world through a private property and so once I have initialized the world, I set the view's world property to the world I have just created (I realize that this creates a cycle, but I need a reference to the world in the drawRect method of the view and the only way I can have it is if I maintain a reference to it from the class).
Since the world's start method is synchronous, I don't start the world up immediately. In the drawRect method I check to see if the world is running. If it is not, I start it up in a background thread. If it is, I examine the world and display all the graphics that I need to.
In the intercept method (which gets called from start running on the background thread), I set setNeedsToDisplay to YES. Since the start method of the world is running in a separate thread, I also have a lock object that I use to synchronize so that I'm not working on the World object while it's being mutated (this part is kind of janky and it's probably not working the way I expect it to - there are more than a few rough spots and I'm simply trying to get a little bit working; I plan to clean up later).
My problem is that the view renders some stuff, and then it pretty much locks up. I can see that the NSLog statements are being called and so the code is running, but nothing is getting updated on the view.
Here's some of the pertinent code:
MasterViewController
#import "MasterViewController.h"
#import "World.h"
#import "InfectableBug.h"
#interface MasterViewController ()
#end
#implementation MasterViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
_worldView = [[WorldView alloc] init];
World* world = [[World alloc] initWithName: #"Bhumi"
rows: 100
columns: 100
iterations: 2000
snapshotInterval: 1
interceptor: _worldView];
for(int i = 0; i < 999; i++) {
NSMutableString* name = [NSMutableString stringWithString: #"HealthyBug"];
[name appendString: [[NSNumber numberWithInt: i] stringValue]];
[world addBug: [[InfectableBug alloc] initWithWorld: world
name: name
layer: #"FirstLayer"
infected: NO
infectionRadius: 1
incubationPeriod: 10
infectionStartIteration: 0]];
}
NSLog(#"Added all bugs. Going to add infected");
[world addBug: [[InfectableBug alloc] initWithWorld: world
name: #"InfectedBug"
layer: #"FirstLayer"
infected: YES
infectionRadius: 1
incubationPeriod: 10
infectionStartIteration: 0]];
[_worldView setWorld: world];
//[world start];
}
return self;
}
- (NSView*) view {
return self.worldView;
}
#end
WorldView
#import "WorldView.h"
#import "World.h"
#import "InfectableBug.h"
#implementation WorldView
#synthesize world;
- (id) initWithFrame:(NSRect) frame {
self = [super initWithFrame:frame];
if (self) {
// Initialization code here.
}
return self;
}
- (void) drawRect:(NSRect) dirtyRect {
CGContextRef myContext = [[NSGraphicsContext currentContext] graphicsPort];
CGContextClearRect(myContext, CGRectMake(0, 0, 1024, 768));
NSUInteger rows = [world rows];
NSUInteger columns = [world columns];
NSUInteger cellWidth = 1024 / columns;
NSUInteger cellHeight = 768 / rows;
if([world running]) {
#synchronized (_lock) {
//Ideally we would need layers, but for now let's just get this to display
NSArray* bugs = [world bugs];
NSEnumerator* enumerator = [bugs objectEnumerator];
InfectableBug* bug;
while ((bug = [enumerator nextObject])) {
if([bug infected] == YES) {
CGContextSetRGBFillColor(myContext, 128, 0, 0, 1);
} else {
CGContextSetRGBFillColor(myContext, 0, 0, 128, 1);
}
NSLog(#"Drawing bug %# at %lu, %lu with width %lu and height %lu", [bug name], [bug x] * cellWidth, [bug y] * cellHeight, cellWidth, cellHeight);
CGContextFillRect(myContext, CGRectMake([bug x] * cellWidth, [bug y] * cellHeight, cellWidth, cellHeight));
}
}
} else {
[world performSelectorInBackground: #selector(start) withObject: nil];
}
}
- (BOOL) isFlipped {
return YES;
}
- (void) intercept: (World *) aWorld {
struct timespec time;
time.tv_sec = 0;
time.tv_nsec = 500000000L;
//nanosleep(&time, NULL);
#synchronized (_lock) {
[self setNeedsDisplay: YES];
}
}
#end
start method in World.m:
- (void) start {
running = YES;
while(currentIteration < iterations) {
#autoreleasepool {
[bugs shuffle];
NSEnumerator* bugEnumerator = [bugs objectEnumerator];
Bug* bug;
while((bug = [bugEnumerator nextObject])) {
NSString* originalLayer = [bug layer];
NSUInteger originalX = [bug x];
NSUInteger originalY = [bug y];
//NSLog(#"Bug %# is going to act and location %i:%i is %#", [bug name], [bug x], [bug y], [self isOccupied: [bug layer] x: [bug x] y: [bug y]] ? #"occupied" : #"not occupied");
[bug act];
//NSLog(#"Bug has acted");
if(![originalLayer isEqualToString: [bug layer]] || originalX != [bug x] || originalY != [bug y]) {
//NSLog(#"Bug has moved");
[self moveBugFrom: originalLayer atX: originalX atY: originalY toLayer: [bug layer] atX: [bug x] atY: [bug y]];
//NSLog(#"Updated bug position");
}
}
if(currentIteration % snapshotInterval == 0) {
[interceptor intercept: self];
}
currentIteration++;
}
}
//NSLog(#"Done.");
}
Please let me know if you'd like to see any other code. I realize that the code is not pretty; I was just trying to get stuff to work and I plan on cleaning it up later. Also, if I'm violating an Objective-C best practices, please let me know!
Stepping out for a bit; sorry if I don't respond immediately!
Whew, quiet a question for probably a simple answer: ;)
UI updates have to be performed on the main thread
If I read your code correctly, you call the start method on a background thread. The start method contains stuff like moveBugFrom:... and also the intercept: method. The intercept method thus calls setNeedsDisplay: on a background thread.
Have all UI related stuff perform on the main thread. Your best bet is to use Grand Central Dispatch, unless you need to support iOS < 4 or OS X < 10.6 (or was it 10.7?), like this:
dispatch_async(dispatch_get_main_queue(), ^{
// perform UI updates
});
I would like to initially set a CGPoint property to a particular point (middle of screen). Other methods may subsequently wish to change this property. My thoughts were to initialise it if empty in the getter, but I get the message invalid argument type 'struct CGPoint' to unary expression. I also tried using if property == nil or 0 but no joy.
Any thoughts?
-(CGPoint)graphOrigin
{
// initialise to centre of screen if has not been set
if(!_graphOrigin) // this expression is causing the problem
{
CGPoint origin = CGPointMake(self.bounds.origin.x + self.bounds.size.width / 2, self.bounds.origin.y + self.bounds.size.height / 2);
_graphOrigin = origin;
}
return _graphOrigin;
}
A CGPoint is a struct, so you can't set it to nil or NULL (it's not a pointer). In a sense, there's really no "uninitialized" state. Perhaps you could use {0.0, 0.0} to designate an unset CGPoint, but that's also a valid coordinate. Or you could use negative x and y values to flag an "uninitialized" point, since negative values can't be valid drawing points, but that's a bit of a hack, too.
Probably your best bet is to do one of two things:
Store the property as a pointer to a CGPoint. This value can be set to NULL when uninitialized. Of course, you have to worry about mallocing and freeing the value.
Store the CGPoint alongside a BOOL called pointInitialized or somesuch, initially set to NO, but set to YES once the point has been initialized. You can even wrap that up in a struct:
struct {
CGPoint point;
BOOL initialized;
} pointData;
An easier way would be to initialize _graphOrigin to CGRectZero and change your if statement for this:
if (!CGPointEqualToPoint(_graphOrigin, CGPointZero)) {
}
CGPoint does not have an uninitialized state. However, if you consider the point (0, 0) as uninitialized, you could use
if (_graphOrigin.x == 0 && _graphOrigin.y == 0)
{
...
This works because when an Objective-C instance is initialized, all its ivar are cleared to bits of zero, which in the CGFloat representation is 0.0.
(Note: The == is fine here even if the operands are CGFloat because we want to compare with the an exact bit pattern (ignoring the issue of -0))
Since CGPointZero (0,0) and any other value you give a point may exist in your context
you may want to initialize an NSValue with your point using:
NSValue *pointVal = [NSValue valueWithCGPoint:point];
You could do this based on some condition and then later test the NSValue for nil.
NSValue can also be added to an array which would allow you to have an array of points should you need.
To get the point later simply use:
CGPoint point = [pointVal CGPointValue];
static CGPoint kInvalidPoint = {.x = NSIntegerMax, .y = NSIntegerMax};
#implementation MyClass
- init()
{
self = [super init];
if (self) {
_oldPoint = kInvalidPoint;
}
return self;
}
- (void)foo
{
if (CGPointEqualToPoint(self.oldPoint, kInvalidPoint)) {
// Invalid point.
return;
}
}
#end
Create two CGPoint properties, that way they are both "uninitialized". Set one of them and use the second one to check whether or not they are equal.
#interface ClassName ()
#property (nonatomic) CGPoint point1;
#property (nonatomic) CGPoint point2;
#end
#implementation ClassName
self.point1 = CGPointMake(69.0f, 180.0f); //arbitrary numbers
//if not equal, then if statement proceeds
if (!CGPointEqualToPoint(self.point1, self.point2) {
//your code here
}
#end
Idk if you'd consider this way hackish though. And I know your question was already answered, but I had kinda the same dilemma till I thought of this.
I've created one of my first apps using Objective-C. Being a noob, there's a lot of stuff I want to do, but don't know how to apply it in Objective-C. Please take a look at the method below (which I created from scratch) and tell me what you would do to make it better. Obviously I've duplicated code across 2 UILabels, but I'd like to simplify that (I hate duplicating code) but I'm unaware what the best way to do it is. I just need suggestions which will help me better understand the right way to do stuff in Objective-C
timeText and dateText are of type UILabel
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
if (isRearranging)
{
NSLog(#"touchesMoved");
NSLog(#"touches=%#,event=%#",touches,event);
//TOUCH INFO
UITouch *touch = [[touches allObjects] objectAtIndex:0];
CGPoint currentLocation = [touch locationInView:touch.view];
CGPoint previousLocation = [touch previousLocationInView:touch.view];
//FRAME INFO
float timeHalfWidth = timeText.frame.size.width / 2;
float timeHalfHeight = timeText.frame.size.height / 2;
CGRect timeTextRect = CGRectMake(timeText.center.x - (timeHalfWidth), timeText.cener.y - (timeHalfHeight), timeText.frame.size.width, timeText.frame.size.height);
float dateHalfWidth = dateText.frame.size.width / 2;
float dateHalfHeight = dateText.frame.size.height / 2;
CGRect dateTextRect = CGRectMake(dateText.center.x - (dateHalfWidth), dateText.center.y - (dateHalfHeight), dateText.frame.size.width, dateText.frame.size.height);
//IF TIME TEXT
if(CGRectContainsPoint(timeTextRect,previousLocation))
{
CGPoint item = timeText.center;
CGPoint diff;
diff.x = previousLocation.x - item.x;
diff.y = previousLocation.y - item.y;
CGPoint newLoc;
newLoc.x = currentLocation.x - diff.x;
newLoc.y = currentLocation.y - diff.y;
if (newLoc.x<timeHalfWidth)
newLoc.x = timeHalfWidth;
if (newLoc.y<timeHalfHeight)
newLoc.y = timeHalfHeight;
[timeText setCenter:(newLoc)];
}
//IF DATE TEXT
if(CGRectContainsPoint(dateTextRect,previousLocation))
{
CGPoint item = dateText.center;
CGPoint diff;
diff.x = previousLocation.x - item.x;
diff.y = previousLocation.y - item.y;
CGPoint newLoc;
newLoc.x = currentLocation.x - diff.x;
newLoc.y = currentLocation.y - diff.y;
if (newLoc.x<dateHalfWidth)
newLoc.x = dateHalfWidth;
if (newLoc.y<dateHalfHeight)
newLoc.y = dateHalfHeight;
[dateText setCenter:(newLoc)];
}
}
touchMoved = YES;
}
Thanks so much for your help!
A first step, independent from the language you are working in, would be to follow DRY - most of your code is the same for both labels.
Then there is already functionality for hit-testing in the SDK, e.g. -hitTest:withEvent: or -pointInside:withEvent::
NSArray *labels = [NSArray arrayWithObjects:timeText, dateText, nil];
for (UILabel *label in labels) {
if ([label pointInside:previousLocation withEvent:nil]) {
[self relocateLabel:label];
break;
}
}
I will answer an additional question posed by asker in a comment. Quote:
What if I wanted to use mixed types in that array? i.e. a couple UILabel and a couple UIImageView. Is there a way to compare types or use generics? This is a poor guess/example for (NSObject *obj in objects) { if (label.type==UILabel) [self relocateLabel:obj]; else if (label.type==UIImageView) [self relocateImage:obj]; }
As Georg Fritzsche answered there, Objective-C messaging is dynamic. Object will be "queried" if it supports that message at runtime, and if so, it will execute the method associated with the message. Method/message name is called a "selector".
If you explicitly want to figure out object's class, you can do that as well.
if([view isKindOfClass:[UILabel class]])
{
// your code here
}
If you just want to figure out if the target object responds to a selector (that is, implements a method):
if([view respondsToSelector:#selector(relocateView:)])
{
// your code here
}
Selectors are derived from method names by omitting arguments themselves, leaving colons intact and appending everything closely. For example, if you had a message send (that is, method call): [thing moveTowardsObject:door movementType:XYZ_CRAWL], its selector would be: moveTowardsObject:movementType: and you'd get it using #selector(moveTowardsObject:movementType:).
In a loop such as what Georg posted, you typically want to just check if the target object responds to a selector, since otherwise an exception would be thrown, and Objective-C code rarely catches exceptions as part of a normal code flow (as opposed to what Python developers do).
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.
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...
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. :-)
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.
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.