AS3 to Cocoa Touch: Array's
So for this topic I will discuss Array’s. So defined by wikipedia
“In computer science an array is a data structure consisting of a group of elements that are accessed by indexing. In most programming languages each element has the same data type and the array occupies a contiguous area of storage.”
So we all know that when we have an array in Actionscript we don’t have to fill it up with objects of the same data type’s, we can use any data type. We’re not restricted. That’s the same in Objective-C. Except 1 little thing. In objective-C if we want to fill up an array it can only be with Objects, not primitives (like int or float, ..). So what we will do is take a couple of examples using an Array in actionscript and converting it to Objective-c. Along the way we will se what is possible and what is not, or what will be different.
So first things first.
#Actionscript var p1 : Person = new Person("john",15); var string : String = new String("lol"); var number : Number = 15; var array : Array = new Array(p1,string,number); trace(array); //output: [object Person],lol,15 trace(array[2]); //output: 15
So what we have done is created 3 variables 1 object of the type Person ( see the previous example ). A simple string and a number. Create an Array and put those 3 variables in the array and trace it.
So how would we do that in Objective-c
#Objective-C Person *p1 = [[Person alloc] initWithName:@"joe" andAge:34]; NSString *string = [NSString stringWithFormat:@"This is a string"]; NSNumber *number = [NSNumber numberWithInt:4]; NSArray *arr = [[NSArray alloc] initWithObjects:p1,string,number,nil]; NSLog(@"array : %@",arr); NSLog(@"array object 2: %@",[mArr objectAtIndex:2]);
And our output should be:
2008-12-15 21:59:58.615 cocoatests[26361:20b] array : (
<Person: 0×524810>,
“This is a string”,
4
)
2008-12-15 21:59:58.615 cocoatests[26361:20b] array object 2: (
4
)
So what we do is exactly the same as in actionscript. Create 3 variables 1 of the type Person instantiate it with 2 parameters “joe” & 34 (as being a method defined in the interface of the Class Person ( if you want to know more about that or it is a little unclear just go back to my previous post about Objects and methods )) We make a String and A Number.
So for our “array part”. We make a new variables of the type NSArray we allocate it to reserve space in the memory, and we immediately initialize it with some objects (being the objects created before). Doing this by using the method initWithObjects: followed by the objects we want to put in our array as a set of parameters. If you look closely enough you would see that we end our set of parameters with “nil”. This is because when we use initWithObjects, under the hood it iterates over every object until it finds nil so it knows it is at the end of the array. Everything that you put behind nil will not be pushed into your array.
So next on.. we want to add some more data to our array.
#Actionscript array.push("foo"); array.push("bar"); array.push(12); trace(array); //output: [object Person],lol,15,foo,bar,12
We us the push method to push new data in to our array (wich still can be of any datatype)
#Objective-C
So at our objective C side we cannot just add new data to an object of type NSArray, instead we have to use NSMutableArray. That’s because NSArray creates static arrays, and NSMutableArray creates dynamic arrays. Actually NSMutableArray is a subclass of NSArray wich adds extra functionality to NSArray such as push or remove new objects to our array.
So what we can do is create a new NSMutableArray or just push our already created array into our new NSMutableArray
#Objective-C //Method 1 NSMutableArray *mArr = [[NSMutableArray alloc] initWithObjects:p1,string,number,nil]; //Method 2 NSMutableArray *mArr = [[NSMutableArray alloc] initWithArray:arr]; [mArr addObject:@"foo"]; [mArr addObject:@"bar"]; [mArr addObject:[NSNumber numberWithInt:15]]; NSLog(@"array : %@",mArr);
Which would result:
2008-12-15 22:24:26.883 cocoatests[26560:20b] array : (
<Person: 0×5229e0>,
“This is a string”,
4,
foo,
bar,
15
)
So what we have done is used the addObject method to add objects to our NSMutableArray. Simple as that. So for removing. We use the same principle only that in objective-c removing or replacing is better supported.
If we would like to remove the first object and the object called “foo” in actionscript we would do it like:
#Actionscript array.splice(0,1); array.splice(array.indexOf("foo"),1); trace(array); //output: lol,15,bar,12
#Objective-C [mArr removeObjectAtIndex:0]; [mArr removeObject:@"foo"]; NSLog(@"array : %@",mArr);
2008-12-15 22:39:14.451 cocoatests[26689:20b] array : (
“This is a string”,
4,
1,
15
)
if you want to know all the add/remove/replace function just go to NSMutableArray Reference
there you will find all the implementations.
So what about sorting ?
#Actionscript var poets:Array = ["Blake", "cummings", "Angelou", "Dante"]; poets.sort(); // default sort trace(poets); // output: Angelou,Blake,Dante,cummings poets.sort(Array.CASEINSENSITIVE); trace(poets); // output: Angelou,Blake,cummings,Dante poets.sort(Array.DESCENDING | Array.CASEINSENSITIVE); // use two options trace(poets); // output: Dante,cummings,Blake,Angelou
The Array class in Actionscript provides you with a couple of static constants that can be given as an argument to the sort method. It simply takes the array and sort it depending on the argument you pass it.
#Objective-C NSArray *poets = [[NSArray alloc] initWithObjects:@"Blake",@"cummings",@"Angelou",@"Dante",nil]; NSLog(@"%@",[poets sortedArrayUsingSelector:@selector(compare:)]); NSLog(@"%@",[poets sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]); NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:nil ascending:NO selector:@selector(caseInsensitiveCompare:)]; NSLog(@"%@",[poets sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]]);
So this code creates exactly the same output as we would have in actionscript.
So for starters the sorting methods we use on the array doesn’t change the array itself as it does in actionscript but it returns a new array. What we can do is instantiate a new array. But for this example as I’m only showing the output of the array i skip that.
So if we look to the reference we see that the NSArray has a couple of methods to do sorting on. I’m going to discuss the 2 most used as from my experience.
The first one is the use of selectors (Selectors are used for method invocation) we use the method sortedArrayUsingSelector and we pass the selector we want to use by telling it is a selector @selector( <your selector > ).
The compare: selector is just going to sort it A-Z / 1-10 (and is defined in NSString, NSNumber..)
what gives the same result as the default sort method in actionscript.
If we wanted to use the caseInsesitiveCompare we just use that selector ( which is defined in NSString)
No for our next example being descending / caseInsensitive we are going to make use of Descriptors which are just separated objects that describe what sorting we want to take place on our array.
For that we use the NSSortDescriptor object. We allocate it you must initialize it with a key (I use nil because we don’t need a key) we pass the NO argument to ascending and we make us of a selector caseInsensitiveCompare like we did in our previous example. Now that our object is created we want to tell the array to sort on that descriptor we use the method sortedArrayUsingDescriptors (it expects an array so we put feed it an array created with our sortDescriptor object init). If we would log that you would see that it would result in a descending / caseInsensitive output.
So that was it for array’s for now. There is a lot more to cover, if you want to see something more clearly just leave a comment, or if something isn’t clear enough, let me know!
Next topic will be XML Parsing.
[...] Tutorial: AS3 tot Cocoa Touch: Array’s So for this topic I will discuss Array
After your:
[mArr addObject:@"foo"];
[mArr addObject:@"bar"];
When you call NSLog, why is “this is a string” in quotes, but foo and bar aren’t? Is this a typo?
That’s simply because there a spaces in that string the quotes “hold it together”
very clear article dude!
You should probably use :
NSString *string = [NSString stringWithString:@"This is a string"];
instead of :
NSString *string = [NSString stringWithFormat:@"This is a string"];
as you don’t have any variable to pass to your format.
Andy – thanks for the tutorial. Definitely came in handy. Any chance you have an example on how to sort on a parameter within an object in Cocoa Touch. In your example, say we wanted to sort on Age within the Person objects. Thanks in advance. Cam.
Andy – I figured it out. Thanks again for the tut and here is how I did it if it helps anyone else:
NSSortDescriptor *sortit = [[NSSortDescriptor alloc] initWithKey:@”andAge” ascending:YES];
[arrayofppl sortUsingDescriptors:[NSArray arrayWithObject:sortit]];
based on the ppl object used before in the tut:
Person *p1 = [[Person alloc] initWithName:@”joe” andAge:34];
Person *p2 = [[Person alloc] initWithName:@”jane” andAge:32];
NSArray *arrayofppl = [[NSArray alloc] initWithObjects:p1,p2,nil];
Do you have a nice example of an array within arrays by any chance? In the AS3 days declaring array [0][0] made this easy but it’s not clear to me how you’d do that in cocoa.
Cheers
Toby
Answered my own question.
If you really need to use lots of nested arrays you can still use a[0][1] which is standard in c, but you need to set it up thus
float a[13][13]
for example.