views:

97

answers:

5

I've checked Google and I haven't found anything that helps. I'm writing a stack class in Objective-C, the stack is based around an NSMutableArray, however, I cannot add any objects to it, it's not throwing any errors in the console, and there are no compile warnings/errors. Here is my code for the stack object.

#import "Stack.h"

@implementation Stack
@synthesize stack;

- (id)init {
    self.stack = [[NSMutableArray alloc] init];
    return self;
}

- (void)push:(id)object { [self.stack addObject:object]; }

- (int)size { return [self.stack count]; }

- (id)pop {
    id obj = [[[self.stack lastObject] retain] autorelease];
    [self.stack removeLastObject];
    return obj;
}

- (id)peek { return [self.stack lastObject]; }

@end

Header:

#import <Cocoa/Cocoa.h>

@interface Stack : NSObject {
    NSMutableArray *stack;
}

- (void)push:(id)object;
- (int)size;
- (id)pop;
- (id)peek;

@property (nonatomic, retain) NSMutableArray *stack;

@end

For the rest of the code, if I call [test_stack size], it returns zero, no matter how many times I push an object, and if I call pop or peek, it simply returns (null).

#import "TRIAL_Stack_Ctrl.h"


@implementation TRIAL_Stack_Ctrl
@synthesize test;

- (IBAction)push:(id)sender {
    [test_stack push:[input stringValue]];
}
- (IBAction)pop:(id)sender {
    [label setStringValue:[NSString stringWithFormat:@"%@", [test_stack pop]]];
}
- (IBAction)peek:(id)sender {
    [label setStringValue:[NSString stringWithFormat:@"%@", [test_stack peek]]];
}
- (IBAction)size:(id)sender {
    [label setStringValue:[NSString stringWithFormat:@"%d", [test_stack size]]];
}

@end

This leads me to believe that it's not pushing the object, is there anything I am doing wrong?

+1  A: 

Change:

- (id)init {
    self.stack = [[NSMutableArray alloc] init];
    return self;
}

to:

- (id)init {
    self = [super init];
    if (self) {
        stack = [[NSMutableArray alloc] init];
    }
    return self;
}
Johan Kool
although this is the standard way of doing things, -[NSObject init] doesn't do anything but return self, and if self is nil init will never be called. Basically what he's doing is okay because he inherits directly from NSObject. Furthermore, he shouldn't be using accessors in an init method.
Jared P
@Jared P: Changed the use of accessor. I am not sure exactly where `self` gets set to the created instance. My suspicion was that `self` would be `nil` when returned from the `-init` method due to him not calling this method on `super`. It sure sounds like he is calling `nil` instead of an instance of his `Stack` class.
Johan Kool
@Johan: self doesn't 'get set' in that sense, it is a hidden parameter to the method, which is actually just a regular C function, with 2 implicit extra parameters (id self, SEL _cmd) before the ones declared. Basically, self is set just before the method is called. The objc runtime checks if the target of the message (the would-be self argument) is nil, and if it does, it simply does not deliver the message. Therefore, self cannot be nil entering ANY objective-c method.
Jared P
@Jared: what he is doing is not OK. The fact that -init in NSObject just returns self is an implementation detail. There is no reason why Apple shouldn't change that in a future release of Cocoa. However, it is not the cause of the problem.
JeremyP
@JermyP: -[NSObject init] returning self is documented very clearly in NSObject's class reference, so I'd hardly call that an implementation detail. Also, @Johan and I are obviously just bickering over conventions -- we know this isn't the problem
Jared P
+1  A: 

Apart from leaking the NSMutableArray, and unnecessary use of self.stack, it looks ok. So it seems your problem is probably in TRIAL_Stack_Ctrl class that you don not show the code to.

If you feel like you are going crazy assertions can help you get to the bottom of what is going on.

- (void)push:(id)object {
  NSParameterAssert(object);
  [stack addObject:object];
  NSAssert([stack count], @"array is empty");
}

They compile away to nothing in release code.

mustISignUp
A: 

Can we see the .h for the implementation? I see you are synthesizing something called 'test' but all the operations are done on something called 'test_stack'. Naming problem? If so, it should probably also be 'self.test_stack'.

ACBurk
+1  A: 

If that really is the full implementation of your TRIAL_Stack_Ctrl class, you're not assigning the test stack instance variable anywhere, so it's nil.

Chuck
+1  A: 

This leads me to believe that it's not pushing the object, is there anything I am doing wrong?

Incorrect assumption. removeLastObject throws an NSRangeException if the mutable array has no objects in it. If you do not see a range exception, when you try to pop an empty stack, the stack itself must be nil.

JeremyP