34

I'm writing an iPhone app, and I'm surprised that there seem to be no NSQueue or NSStack classes in Apple's Foundation Framework. I see that it would be quite easy to roll my own, starting with an NSMutableArray, so I'll do that unless I've missed something. Have I missed something?

Tommy Herbert
  • 20,407
  • 14
  • 52
  • 57

8 Answers8

29

Here's my Stack class, in case it's useful to those who come after me. As you can see, the pop method involves enough code that you'd want to factor it out.

Stack.h:

#import <Foundation/Foundation.h>

@interface Stack : NSObject {
    NSMutableArray *contents;
}

- (void)push:(id)object;
- (id)pop;

@end

Stack.m

#import "Stack.h"

@implementation Stack

// superclass overrides

- (id)init {
    if (self = [super init]) {
        contents = [[NSMutableArray alloc] init];
    }
    return self;
}

- (void)dealloc {
    [contents release];
    [super dealloc];
}

// Stack methods

- (void)push:(id)object {
    [contents addObject:object];
}

- (id)pop {
    id returnObject = [[contents lastObject] retain];
    if (returnObject) {
            [contents removeLastObject];
    }
    return [returnObject autorelease];
}

@end
Dario
  • 671
  • 5
  • 14
Tommy Herbert
  • 20,407
  • 14
  • 52
  • 57
  • 2
    For the pop method, you can save a little bit of typing by using [contents lastObject]. That'll return nil if the array is empty. I ended up implementing the methods as a category on NSMutableArray. Thanks for the code! – Eric Andres Oct 18 '12 at 05:39
  • 1
    Personally, I'd probably just add the `pop` method to `NSMutableArray` via a category and use an `NSMutableArray` directly wherever I needed a stack, rather than creating an entirely new `Stack` class. Most languages I've used before don't have dedicated stack classes and use arrays as stacks. I suppose I can see the elegance from a readability perspective of having a class that can *only* be used as a stack, though. – Mark Amery Aug 27 '13 at 16:40
22

as far as I know there is no generic class avaialbe. Try using the NSMutableArray, add via addObject and get first/last via objectAtIndex and removeObjectAtIndex.

Michael W.
  • 558
  • 4
  • 15
  • 2
    Note that `removeObjectAtIndex` is an O(n) operation, so this is probably not the best approach for queues when the number of items is expected to be large. Using a linked list (which allows for efficient addition and removal from any point) is probably much better, but unfortunately this is another common collection type missing from foundation, so you'll have to implement this, too. – Jules Jul 10 '18 at 03:17
7

Another easy way would be to extend NSMutableArray's capabilities by making use of Objective C's categories. You can do that by adding two files to your project:

NSMutableArray+Stack.h

@interface NSMutableArray (StackExtension)

- (void)push:(id)object;
- (id)pop;

@end

NSMutableArray+Stack.m

#import "NSMutableArray+Stack.h"

@implementation NSMutableArray (StackExtension)

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

- (id)pop {
    id lastObject = [self lastObject];
    [self removeLastObject];
    return lastObject;
}

@end

Now you can use a regular NSMutableArray in every other file of your project like a stack and call push or pop on that object. Don't forget to #import NSMutableArray+Stack.h in those files. Here is some sample code how you can use your new NSMutableArray as a stack:

NSMutableArray *myStack = [[NSMutableArray alloc] init]; // stack size = 0

NSString *aString = @"hello world";
[myStack push:myString];            // stack size = 1

NSString *anotherString = @"hello universe";
[myStack push:anotherString];       // stack size = 2

NSString *topMostStackObject; 

topMostStackObject = [myStack pop]; // stack size = 1
NSLog("%@",topMostStackObject);

topMostStackObject = [myStack pop]; // stack size = 0
NSLog("%@",topMostStackObject);

The log output will be:

hello universe
hello world
Mischa
  • 15,816
  • 8
  • 59
  • 117
6

I'm a bit late to this party, but are you aware of CHDataStructures?

http://cocoaheads.byu.edu/code/CHDataStructures

occulus
  • 16,959
  • 6
  • 53
  • 76
5

I have put a working iOS Objective C queue object on GitHub. The code was taken from various posts and by no means is owned by me.

https://github.com/esromneb/ios-queue-object/

If you see any problems please fork, and make a pull request!

benathon
  • 7,455
  • 2
  • 41
  • 70
1

ObjectiveSugar is a very popular CocoaPod that provides, among a bunch of other great stuff, push and pop API calls on NSMutableArray. Sure, it's not in the iOS SDK, but I'm sharing it here because I was looking for the same thing, and this was the solution I went with (and it certainly didn't hurt that we were already using this CocoaPod in our codebase).

Gabe
  • 727
  • 1
  • 6
  • 8
1

Yes, an NSMutableArray doubles as a stack or queue. (It would be slightly inefficient as a queue.)

You could also use C++'s stack and queue adapter, but it makes memory management a bit messy if you want to store Objective-C objects with it.

kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
0

No. You missed nothing. That's all. Objective-C is higher level language look like C. Low level control is not required.

Cocoa classes are designed for easier use than efficiency. If you want to deal with performance, you have an option of raw C (or C++) implementation. Otherwise, just use easy way. Of course, early-optimization is evil.

If you want a kind of encapsulation, just make a new class which contains NSMutableArray within it. Hide inner NSMutableArray and just expose what you want. But you'll realize this is unnecessary.

eonil
  • 83,476
  • 81
  • 317
  • 516
  • 2
    Thanks. It's code duplication I'm worried about, rather than encapsulation. – Tommy Herbert Sep 07 '10 at 12:51
  • NOT using a queue is evil !, do you have any idea of the impact that has ? NSMutable arrays are NOT just designed for ease of use (they aren't easy to use AT ALL by the way !), they are actually efficient, and like mentioned above, can be used to implement queues. – Pizzaiola Gorgonzola Aug 07 '13 at 10:21
  • 1
    @PizzaiolaGorgonzola I am sorry but it's very hard to understand what you really mean in this comment. And I never told Cocoa classes are *inefficient*. What I told was Cocoa classes are relatively less efficient and more easier to use when compared to their C (or C++) level counterparts. – eonil Aug 08 '13 at 03:46