Initializing child objects from parent - objective-c

I'm having a bit of a structural dilemma with designing my app. I want to use a series of nested loops to create a large amount of custom objects. Once those objects are created, I want to store them all into an object which is collection of those objects.
Visualized:
#interface CollectionOfObjectA : NSObject
#property (nonatomic, strong) NSArray *reference;
#end
#implementation CollectionOfObjectA
-(CollectionOfObjectA *)init{
NSMutableArray *ref = [[NSMutableArray alloc] init];
for(int i=0; i < largeNumber; i++){ // There will be nested loops.
NSString *str = #"string made from each loop index";
ObjA *obj = [[ObjA alloc] initWithIndexes: str];
[ref addObject: obj];
}
self.reference = [ref copy];
}
#end
#interface ObjA : CollectionOfObjA
// several properties
#end
#implementation ObjA
-(ObjA *)initWithIndexes:(NSString *)indexes{
self = [super init];
// Use passed indexes to create several properties for this object.
return self;
}
#end
What would be the best way about creating this object which is a collection of child objects? Am I incorrect in making ObjA a child of CollectionOfObjectA -- should it be the other way around? Any help would be greatly appreciated.

Ok, my advise: I have nearly ~30 custom objects. Like events. After that I make class Factory which can create all of them. And also this class Factory have method: getAllObjects.
Like this:
#include "CustomEvent.h"
#interface EventFactory
+(NSArray*)allEvents;
#end
#implementation EventFactory
-(CustomEvent*)firstEvent{/*something here*/}
-(CustomEvent*)secondEvent{/*yes, you should init custom object here*/}
-(CustomEvent*)thirdEvent{/*and after that you can put them*/}
/*
...
*/
+(NSArray*)allEvents{
EventFactory* factory = [[EventFactory alloc]init];
return #[
[factory firstEvent],
[factory secondEvent],
/*...*/
[factory lastEvent]
];
}
#end
Here I return NSArray because I don't need, actually, know anything of them. They already have handlers and they subscribed on custom notifications. You can return NSDictionary for better access.
P.S: for better explanation you can read article in wiki about Factory pattern
But, if you want better manipulation of objects, you should use other pattern:Composite pattern.
What I mean?
#interface EventCollection{
NSMutableArray* YourArray;
}
-(void)addCustomEvent:(CustomEvent*)event atPosition:(NSInteger)position;
-(void)removeCustomEventAtPosition:(NSInteger)position;
-(void)seeAllEvents;
-(void)seeAllPositions; /*if you want*/
-(void)doesThisPositionAvailable:(NSInteger)position;
#end
#implementation EventCollection
-(void)addCustomEvent:(CustomEvent*)event atPosition:(NSInteger)position{
/*maybe you should check if this position available*/
if ([self doesThisPositionAvailable:position]){
/*add element and save position*/
}
}
-(void)removeCustomEventAtPosition:(NSInteger)position{
if (![self doesThisPositionAvailable:position]){
/*destroy element here*/
}
}
-(void)seeAllEvents{
/*yes, this method is the main method, you must store somewhere your objects.
you can use everything, what you want, but don't share your realization.
maybe, you want use array, so, put it as hidden variable. and init at the initialization of your collection
*/
for (CustomEvent* event in YourArray){
[event description];
}
}
#end

Related

Objective-C class as NSMutableArray

Very simple question. Is it possible to create a class which is a list by it self? I mean:
I do
taskList *taskList1 = [[taskList alloc] init];
And than simply:
taskList1 addObject:[task1]
May seem stupid, but I'm totally new to O-C syntax
I'd need two methods:
-(instancetype) init;
which just initialize as an empty list
+(instancetype)taskList;
to allocate taskList instance
and last thing:
In interface i use:
#interface taskList : NSObject
or
#interface taskList : NSMuttableArray
I got stuck on something specific, didn't I? I'm sorry that I bother you with my programming level.
Alright, I gave up, just last question, because I have to finish it very soon.
I changed my approach I added
#property NSMutableArray *list;
Why does this:
taskList *TL1 =[taskList initTaskList];
task *task1 = [[task alloc] init];
task *task2 = [[task alloc] init];
TL1.list addObject:[task1];
doesn't work, I have "Expected identifier" Error
If you read the subclassing notes on NSArray / NSMutableArray you'll see that Apple recommend against subclassing them because they are a class cluster. (i.e. what you really get when you ask for one is an undocumented subclass, and the initialiser decides which undocumented subclass to return to you based on some undocumented qualifiers..
So just make an NSObject subclass which owns a (private) strong property of type NSMutableArray, and publish an api to access that array..
eg
#import "modelList.h"
//dont worry header is empty, its up to you to do that.. this is a subclass on NSObject
#interface modelList()
#property (strong, nonatomic) NSMutableArray *backingArray;
#end
#implementation modelList
#synthesize backingArray = _backingArray;
-(instancetype )init{
if (self = [super init]) {
[self setBackingArray:[[NSMutableArray alloc]init]];
}
return self;
}
//public API (the stuff that is prototyped in the header..)
-(id)objectAtIndex:(NSUInteger )index{
return [self.backingArray objectAtIndex:index];
}
-(BOOL )containsObject:(id)object{
return [self.backingArray containsObject:object];
}
-(void )addObject:(id)object{
//example application, qualifying object..
if ([object conformsToProtocol:#protocol(NSCoding)]) {
[self.backingArray addObject:object];
}
}
-(NSUInteger )count{
return [self.backingArray count];
}
//etc etc declare publicly the things you need to get the job done
#end
so far this is just a face for a mutable array obviously, but it gives you a place for whatever other model logic you need. good luck

Global variable NSMuteableArray using Singleton Class

I'm having trouble creating a nice way of passing a collection around to different view controllers. For example, I created a custom class called Message with a bunch of attributes. I want to have a global NSMutableArray of those stored in a global variable of sorts called messages that I can add to or get from anywhere. Everyone on Stackoverflow says not to use your delagate class to store global variables so I created a singleton class called Shared. In there I created a property for the NSMutableArray called messages like this:
#interface Shared : NSObject {
}
#property (nonatomic, retain) NSMutableArray *messages;
+(Shared *) sharedInstance;
#end
And my .h file is (the important part):
#import "Shared.h"
static Shared* sharedInstance;
#implementation Shared
#synthesize messages;
static Shared *sharedInstance = nil;
-(id) init {
self = [super init];
if (self != nil){
}
return self;
}
-(void) initializeSharedInstance {
}
+ (Shared *) sharedInstance{
#synchronized(self) {
if (sharedInstance == nil){
sharedInstance = [[self alloc] init];
[sharedInstance initializeSharedInstance];
}
return (sharedInstance);
}
}
In my other view controller, I first import "Shared.h", then try this:
[[Shared sharedInstance].messages addObject:m];
NSLog([NSString stringWithFormat:#"Shared messages = %#", [Shared sharedInstance].messages]);
It keeps printing null instead of the the collection of m objects. Any thoughts?
You need to have a static variable.
In .h:
#interface Shared : NSObject
{
NSMutableArray *messages;
}
#property (nonatomic, retain) NSMutableArray *messages;
+ (Shared*)sharedInstance;
#end
in .m:
static Shared* sharedInstance;
#implementation Shared
#synthesize messages;
+ (Shared*)sharedInstance
{
if ( !sharedInstance)
{
sharedInstance = [[Shared alloc] init];
}
return sharedInstance;
}
- (id)init
{
self = [super init];
if ( self )
{
messages = [[NSMutableArray alloc] init];
}
return self;
}
A thought:
#synthesize generates setter and getter methods, it doesn't init your variable. Where do you do that? I can't see it in the excerpts you posted.
The following is not an answer to your issue, but instead a suggestion to an alternative approach that (in my opinion) is 'cleaner' in use.
An alternative to using a Singleton to store app-wide could be to define a class with class methods that retrieves values from the NSUserDefaults. This class could be imported into the prefix header (*.pch) so you can access it from every other class in the project.
Methods inside this class could look like this:
inside Settings.h:
// for this example I'll use the prefix for a fictional company called SimpleSoft (SS)
extern NSString *kSSUserLoginNameKey;
+ (NSString *)userLoginName;
+ (void)setUserLoginName:(NSString *)userLoginName;
inside Settings.m:
kSSUserLoginNameKey = #"SSUserLoginNameKey";
+ (NSString *)userLoginName
{
return [[NSUserDefaults standardUserDefaults] valueForKey:kSSUserLoginNameKey];
}
+ (void)setUserLoginName:(NSString *)userLoginName
{
[[NSUserDefaults standardUserDefaults] setValue:userLoginName forKey:kSSUserLoginNameKey];
[[NSUserDefaults standardUserDefaults] synthesize];
}
Of course in a setup like this NSUserDefaults is the singleton that is being accessed through a convenience class. This class acts as a wrapper around the NSUserDefaults singleton. Values can be accessed like this:
NSString userLoginName = [Settings userLoginName];
[Settings setUserLoginName:#"Bob"];
Other objects -like Arrays- could be accessed in much the same way. One thing to be careful with (much the same as with your current approach) is to be careful not to access a class like this from every other class. Components that are intended to be reusable should pass values, so the components of the application don't become too tightly coupled to the settings class.

NSMutableArray - force the array to hold specific object type only

Is there a way to force NSMutableArray to hold one specific object type only?
I have classes definitions as follow:
#interface Wheel:NSObject
{
int size;
float diameter;
}
#end
#interface Car:NSObject
{
NSString *model;
NSString *make;
NSMutableArray *wheels;
}
#end
How can I force wheels array to hold Wheel objects only with code? (and absolutely not other objects)
Update in 2015
This answer was first written in early 2011 and began:
What we really want is parametric polymorphism so you could declare, say, NSMutableArray<NSString>; but alas such is not available.
In 2015 Apple apparently changed this with the introduction of "lightweight generics" into Objective-C and now you can declare:
NSMutableArray<NSString *> *onlyStrings = [NSMutableArray new];
But all is not quite what it seems, notice the "lightweight"... Then notice that the initialisation part of the above declaration does not contain any generic notation. While Apple have introduced parametric collections, and adding a non-string directly to the above array, onlyStrings, as in say:
[onlyStrings addObject:#666]; // <- Warning: Incompatible pointer types...
will illicit the warning as indicated, the type security is barely skin deep. Consider the method:
- (void) push:(id)obj onto:(NSMutableArray *)array
{
[array addObject:obj];
}
and the code fragment in another method of the same class:
NSMutableArray<NSString *> *oops = [NSMutableArray new];
[self push:#"asda" onto:oops]; // add a string, fine
[self push:#42 onto:oops]; // add a number, no warnings...
What Apple have implemented is essentially a hinting system to assist with automatic inter-operation with Swift, which does have a flavour of type-safe generics. However on the Objective-C side, while the compiler provides some extra hints the system is "lightweight" and type-integrity is still ultimately down to the programmer - as is the Objective-C way.
So which should you use? The new lightweight/pseudo generics, or devise your own patterns for your code? There really is no right answer, figure out what makes sense in your scenario and use it.
For example: If you are targeting interoperation with Swift you should use the lightweight generics! However if the type integrity of a collection is important in your scenario then you could combine the lightweight generics with your own code on the Objective-C side which enforces the type integrity that Swift will on its side.
The Remainder of the 2011 Answer
As another option here is a quick general subclass of NSMutableArray which you init with the kind of object you want in your monomorphic array. This option does not give you static type-checking (in as much as you ever get it in Obj-C), you get runtime exceptions on inserting the wrong type, just as you get runtime exceptions for index out of bounds etc.
This is not thoroughly tested and assumes the documentation on overriding NSMutableArray is correct...
#interface MonomorphicArray : NSMutableArray
{
Class elementClass;
NSMutableArray *realArray;
}
- (id) initWithClass:(Class)element andCapacity:(NSUInteger)numItems;
- (id) initWithClass:(Class)element;
#end
And the implementation:
#implementation MonomorphicArray
- (id) initWithClass:(Class)element andCapacity:(NSUInteger)numItems
{
elementClass = element;
realArray = [NSMutableArray arrayWithCapacity:numItems];
return self;
}
- (id) initWithClass:(Class)element
{
elementClass = element;
realArray = [NSMutableArray new];
return self;
}
// override primitive NSMutableArray methods and enforce monomorphism
- (void) insertObject:(id)anObject atIndex:(NSUInteger)index
{
if ([anObject isKindOfClass:elementClass]) // allows subclasses, use isMemeberOfClass for exact match
{
[realArray insertObject:anObject atIndex:index];
}
else
{
NSException* myException = [NSException
exceptionWithName:#"InvalidAddObject"
reason:#"Added object has wrong type"
userInfo:nil];
#throw myException;
}
}
- (void) removeObjectAtIndex:(NSUInteger)index
{
[realArray removeObjectAtIndex:index];
}
// override primitive NSArray methods
- (NSUInteger) count
{
return [realArray count];
}
- (id) objectAtIndex:(NSUInteger)index
{
return [realArray objectAtIndex:index];
}
// block all the other init's (some could be supported)
static id NotSupported()
{
NSException* myException = [NSException
exceptionWithName:#"InvalidInitializer"
reason:#"Only initWithClass: and initWithClass:andCapacity: supported"
userInfo:nil];
#throw myException;
}
- (id)initWithArray:(NSArray *)anArray { return NotSupported(); }
- (id)initWithArray:(NSArray *)array copyItems:(BOOL)flag { return NotSupported(); }
- (id)initWithContentsOfFile:(NSString *)aPath { return NotSupported(); }
- (id)initWithContentsOfURL:(NSURL *)aURL { return NotSupported(); }
- (id)initWithObjects:(id)firstObj, ... { return NotSupported(); }
- (id)initWithObjects:(const id *)objects count:(NSUInteger)count { return NotSupported(); }
#end
Use as:
MonomorphicArray *monoString = [[MonomorphicArray alloc] initWithClass:[NSString class] andCapacity:3];
[monoString addObject:#"A string"];
[monoString addObject:[NSNumber numberWithInt:42]]; // will throw
[monoString addObject:#"Another string"];
Since Xcode 7, generics are available in Objective-C.
You can declare a NSMutableArray as:
NSMutableArray <Wheel*> *wheels = [[NSMutableArray alloc] initWithArray:#[[Wheel new],[Wheel new]];
The compiler will give you a warning if you try to put non-Wheel objects in the array.
I could be wrong (I'm a noob), but I think, if you create a custom protocol and make sure the objects you are adding to the array follow the same protocol, then when you declare the array you use
NSArray<Protocol Name>
That should prevent objects being added that do not follow the said protocol.
as per i know.. before you added any object in wheels mutableArray, u have to add some check mark. Is the object which i am adding is class "wheel". if it is then add, other wise not.
Example:
if([id isClassOf:"Wheel"] == YES)
{
[array addObject:id)
}
Something like this. i dont remember the exact syntax.
I hope this will help (and work... :P )
Wheel.h file:
#protocol Wheel
#end
#interface Wheel : NSObject
#property ...
#end
Car.h file:
#import "Wheel.h"
#interface Car:NSObject
{
NSString *model;
NSString *make;
NSMutableArray<Wheel, Optional> *wheels;
}
#end
Car.m file:
#import "Car.h"
#implementation Car
-(id)init{
if (self=[super init]){
self.wheels = (NSMutableArray<Wheel,Optional>*)[NSMutableArray alloc]init];
}
return self;
}
#end
Xcode 7 allows you to define Arrays, Dictionaries, and even your own Classes as having generics. The array syntax is as follows:
NSArray<NSString*>* array = #[#"hello world"];
I don't believe there's any way to do it with NSMutableArray out of the box. You could probably enforce this by subclassing and overriding all the constructors and insertion methods, but it's probably not worth it. What are you hoping to achieve with this?
That's not possible; an NSArray (whether mutable or not) will hold any object type. What you can do is to create your own custom subclasses as already suggested by Jim. Alternatively, if you wanted to filter an array to remove objects that weren't of the type you want, then you could do:
- (void)removeObjectsFromArray:(NSMutableArray *)array otherThanOfType:(Class)type
{
int c = 0;
while(c < [array length])
{
NSObject *object = [array objectAtIndex:c];
if([object isKindOfClass:type])
c++;
else
[array removeObjectAtIndex:c];
}
}
...
[self removeObjectsFromArray:array otherThanOfType:[Car class]];
Or make other judgments based on the result of isKindOfClass:, e.g. to divide an array containing a mixture of Cars and Wheels into two arrays, each containing only one kind of object.
You can use the nsexception if you dont have the specific object.
for (int i = 0; i<items.count;i++) {
if([[items objectAtIndex:i] isKindOfClass:[Wheel class]])
{
// do something..!
}else{
[NSException raise:#"Invalid value" format:#"Format of %# is invalid", items];
// do whatever to handle or raise your exception.
}
}
Here's something I've done to avoid subclassing NSMutableArray: use a category. This way you can have the argument and return types you want. Note the naming convention: replace the word "object" in each of the methods you will use with the name of the element class. "objectAtIndex" becomes "wheelAtIndex" and so on. This way there's no name conflict. Very tidy.
typedef NSMutableArray WheelList;
#interface NSMutableArray (WheelList)
- (wheel *) wheelAtIndex: (NSUInteger) index;
- (void) addWheel: (wheel *) w;
#end
#implementation NSMutableArray (WheelList)
- (wheel *) wheelAtIndex: (NSUInteger) index
{
return (wheel *) [self objectAtIndex: index];
}
- (void) addWheel: (wheel *) w
{
[self addObject: w];
}
#end
#interface Car : NSObject
#property WheelList *wheels;
#end;
#implementation Car
#synthesize wheels;
- (id) init
{
if (self = [super init]) {
wheels = [[WheelList alloc] initWithCapacity: 4];
}
return self;
}
#end
protocol maybe a good idea:
#protocol Person <NSObject>
#end
#interface Person : NSObject <Person>
#end
to use:
NSArray<Person>* personArray;
There is one-header file project which allows this:
Objective-C-Generics
Usage:
Copy ObjectiveCGenerics.h to your project.
When defining a new class use the GENERICSABLE macro.
#import "ObjectiveCGenerics.h"
GENERICSABLE(MyClass)
#interface MyClass : NSObject<MyClass>
#property (nonatomic, strong) NSString* name;
#end
Now you can use generics with arrays and sets just as you normally do in Java, C#, etc.
Code:

Shared array between multiple classes

I have an array "myArr" which contains objects of custom class..e.g. objs of type MyClass
I need to share this array across multiple classes..
Could you please help me with the exact code that I should be using..
I have referred Singleton patter on Apple and other references, but it is all ver confusing to me...So it will be great if you could highlight the things/code that I need to add.
I recommend that you read up on object delegation.
#property (nonatomic,copy) NSArray *myArr;
On your other classes, implement a delegate object that will point to this class, then you could use:
NSArray *retrievedArray = [self.delegate myArr];
Edit: If you are interested to use only Singleton i believe it would be something along this way:
static MyClass *obj = nil;
On your class with the array, create a class method to return a Singleton object
+(MyClass*) sharedInstance {
if (obj) {
obj = [[self alloc]init];
}
return obj;
}
On your other classes you could just use
NSArray *retrievedArray = [[MyClass sharedInstance] myArr];
to get back the array.
Cheers.
I’d stay away from singletons. As the array is some kind of model (in the Model–View–Controller sense), other classes should depend on it:
#interface ControllerA : UIViewController {}
#property(retain) NSArray *array;
#end
#interface ControllerB : UIViewController {}
#property(retain) NSArray *array;
#end
Now the question changes into “how do I supply the depency.” You can do this using Interface Builder or supply the array when the depending objects are built. For example I sometimes have a method called setupObjectGraph in my application delegate that creates class instances and connects them together:
- (void) setupObjectGraph
{
mainController = [[MainController alloc] init…];
[mainController setThis…];
[mainController setThat…];
OtherController *bar = [[OtherController alloc] init…];
[bar setThis…];
[bar setThat…];
[mainController setBar:bar];
[bar release];
…
}
- (void) applicationDidFinishLaunchingOrWhatever
{
[self setupObjectGraph];
[window addSubview:[mainController view]];
[window makeKeyAndVisible];
}
This is not perfect (it does not scale very well), but it works for many applications and it’s much better than singletons. This sounds like a trifle issue, but it affects your overall design a lot, so it makes sense to think it through.

How do I make and use a Queue in Objective-C?

I want to use a queue data structure in my Objective-C program. In C++ I'd use the STL queue. What is the equivalent data structure in Objective-C? How do I push/pop items?
Ben's version is a stack instead of a queue, so i tweaked it a bit:
NSMutableArray+QueueAdditions.h
#interface NSMutableArray (QueueAdditions)
- (id) dequeue;
- (void) enqueue:(id)obj;
#end
NSMutableArray+QueueAdditions.m
#implementation NSMutableArray (QueueAdditions)
// Queues are first-in-first-out, so we remove objects from the head
- (id) dequeue {
// if ([self count] == 0) return nil; // to avoid raising exception (Quinn)
id headObject = [self objectAtIndex:0];
if (headObject != nil) {
[[headObject retain] autorelease]; // so it isn't dealloc'ed on remove
[self removeObjectAtIndex:0];
}
return headObject;
}
// Add to the tail of the queue (no one likes it when people cut in line!)
- (void) enqueue:(id)anObject {
[self addObject:anObject];
//this method automatically adds to the end of the array
}
#end
Just import the .h file wherever you want to use your new methods, and call them like you would any other NSMutableArray methods.
I wouldn't say that using NSMutableArray is necessarily the best solution, particularly if you're adding methods with categories, due to the fragility they can cause if method names collide. For a quick-n-dirty queue, I'd use the methods to add and remove at the end of a mutable array. However, if you plan to reuse the queue, or if you want your code to be more readable and self-evident, a dedicated queue class is probably what you want.
Cocoa doesn't have one built in, but there are other options, and you don't have to write one from scratch either. For a true queue that only adds and removes from the ends, a circular buffer array is an extremely fast implementation. Check out CHDataStructures.framework, a library/framework in Objective-C that I've been working on. It has a variety of implementations of queues, as well as stacks, deques, sorted sets, etc. For your purposes, CHCircularBufferQueue is significantly faster (i.e. provable with benchmarks) and more readable (admittedly subjective) than using an NSMutableArray.
One big advantage of using a native Objective-C class instead of a C++ STL class is that it integrates seamlessly with Cocoa code, and works much better with encode/decode (serialization). It also works perfectly with garbage collection and fast enumeration (both present in 10.5+, but only the latter on iPhone) and you don't have to worry about what is an Objective-C object and what is a C++ object.
Lastly, although NSMutableArray is better than a standard C array when adding and removing from either end, it's also not the fastest solution for a queue. For most applications it is satisfactory, but if you need speed, a circular buffer (or in some cases a linked list optimized to keep cache lines hot) can easily trounce an NSMutableArray.
As far as I know, Objective-C does not provide a Queue data structure. Your best bet is to create an NSMutableArray, and then use [array lastObject], [array removeLastObject] to fetch the item, and [array insertObject:o atIndex:0]...
If you're doing this a lot, you might want to create an Objective-C category to extend the functionality of the NSMutableArray class. Categories allow you to dynamically add functions to existing classes (even the ones you don't have the source for) - you could make a queue one like this:
(NOTE: This code is actually for a stack, not a queue. See comments below)
#interface NSMutableArray (QueueAdditions)
- (id)pop;
- (void)push:(id)obj;
#end
#implementation NSMutableArray (QueueAdditions)
- (id)pop
{
// nil if [self count] == 0
id lastObject = [[[self lastObject] retain] autorelease];
if (lastObject)
[self removeLastObject];
return lastObject;
}
- (void)push:(id)obj
{
[self addObject: obj];
}
#end
There's no real queue collections class, but NSMutableArray can be used for effectively the same thing. You can define a category to add pop/push methods as a convenience if you want.
Yes, use NSMutableArray. NSMutableArray is actually implemented as 2-3 tree; you typically need not concern yourself with the performance characteristics of adding or removing objects from NSMutableArray at arbitrary indices.
re:Wolfcow -- Here is a corrected implementation of Wolfcow's dequeue method
- (id)dequeue {
if ([self count] == 0) {
return nil;
}
id queueObject = [[[self objectAtIndex:0] retain] autorelease];
[self removeObjectAtIndex:0];
return queueObject;
}
The solutions that use a category on NSMutableArray are not true queues, because NSMutableArray exposes operations that are a superset of queues. For example, you should not be allowed to remove an item from the middle of a queue (as those category solutions still let you do). It is best to encapsulate functionality, a major principle of object oriented design.
StdQueue.h
#import <Foundation/Foundation.h>
#interface StdQueue : NSObject
#property(nonatomic, readonly) BOOL empty;
#property(nonatomic, readonly) NSUInteger size;
#property(nonatomic, readonly) id front;
#property(nonatomic, readonly) id back;
- (void)enqueue:(id)object;
- (id)dequeue;
#end
StdQueue.m
#import "StdQueue.h"
#interface StdQueue ()
#property(nonatomic, strong) NSMutableArray* storage;
#end
#implementation StdQueue
#pragma mark NSObject
- (id)init
{
if (self = [super init]) {
_storage = [NSMutableArray array];
}
return self;
}
#pragma mark StdQueue
- (BOOL)empty
{
return self.storage.count == 0;
}
- (NSUInteger)size
{
return self.storage.count;
}
- (id)front
{
return self.storage.firstObject;
}
- (id)back
{
return self.storage.lastObject;
}
- (void)enqueue:(id)object
{
[self.storage addObject:object];
}
- (id)dequeue
{
id firstObject = nil;
if (!self.empty) {
firstObject = self.storage.firstObject;
[self.storage removeObjectAtIndex:0];
}
return firstObject;
}
#end
this is my implementation, hope it helps.
Is kind of minimalistic, so you must keep the track of the head by saving the new head at pop and discarding the old head
#interface Queue : NSObject {
id _data;
Queue *tail;
}
-(id) initWithData:(id) data;
-(id) getData;
-(Queue*) pop;
-(void) push:(id) data;
#end
#import "Queue.h"
#implementation Queue
-(id) initWithData:(id) data {
if (self=[super init]) {
_data = data;
[_data retain];
}
return self;
}
-(id) getData {
return _data;
}
-(Queue*) pop {
return tail;
}
-(void) push:(id) data{
if (tail) {
[tail push:data];
} else {
tail = [[Queue alloc]initWithData:data];
}
}
-(void) dealloc {
if (_data) {
[_data release];
}
[super release];
}
#end
Is there some particular reason you cannot just use the STL queue? Objective C++ is a superset of C++ (just use .mm as the extension instead of .m to use Objective C++ instead of Objective C). Then you can use the STL or any other C++ code.
One issue of using the STL queue/vector/list etc with Objective C objects is that they do not typically support retain/release/autorelease memory management. This is easily worked around with a C++ Smart Pointer container class which retains its Objective C object when constructed and releases it when destroyed. Depending on what you are putting in the STL queue this is often not necessary.
Use NSMutableArray.