This is part of an ELC Tech Network

Objective-C Tutorial: NSArray

Here at iCodeblog, we have been showing you guys how to create many different types of applications from the ground up.  Well, today I decided to do something different and get down to some of the nitty gritty of a structure we rely heavily on in objective-C.

The NSArray is a huge workhorse that we use quite frequently without even thinking about it.  The NSArray class isn’t just your ordinary array.  Not only does it provide random access, but it also dynamically re-sizes when you add new objects to it and has many methods to make our lives easier.  While I won’t go over every method in NSArray (there are quite a few), I will discuss some of the more important ones that are most commonly used.  Let’s take a closer look at this class.

Factory Methods

Factory methods are static methods that build new instances of NSArrays from given parameters and return them.  The table below details on all of the factory methods for the NSArray class.

+ (id)array Creates and returns an empty array
+ (id)arrayWithArray:(NSArray *)anArray Creates and returns an array containing the objects in another given array.
+ (id)arrayWithContentsOfFile:(NSString *)aPath Creates and returns an array containing the contents of the file specified by a given path. * The file must be of type .plist for this method to work
+ (id)arrayWithContentsOfURL:(NSURL *)aURL Similar to arrayWithContentsOfFile except it will load the .plist remotely from a given website. This would be a very simple way to get data from a web service.
+ (id)arrayWithObject:(id)anObject Creates and returns an array containing a given object. This will just be a 1 element array
+ (id)arrayWithObjects:(id)firstObj, … This method is used when you have multiple objects on hand and want easily insert them into an array. Make sure the last element you add is nil or this method won’t work.
+ (id)arrayWithObjects:(const id *)objects count:(NSUInteger)count Creates and returns an array that includes a given number of objects from a given C array.

Here is some example usage of building NSArrays with these factory methods…

// I am using strings, but you can add just about any object to an NSArray
 
// Creates an NSArray with one object
NSArray  * myArray = [NSArray arrayWithObject:@"foo"];
 
// Creates an NSArray with multiple objects. Don't forget to add nil as the last object
NSArray  * myArray2 = [NSArray arrayWithObjects:@"foo",@"bar",@"baz",nil];
 
// Creates an NSArray from another NSArray
NSArray * myArray3 = [NSArray arrayWithArray:myArray2];
 
// This will create an NSArray from data on iCodeBlog.  Go ahead and try it out, this file exists on our servers and contains valid data.
NSArray * myArray4 = [NSArray arrayWithContentsOfURL:[NSURL URLWithString:@"http://icodeblog.com/wp-content/uploads/2009/08/foo.plist"]];

You can also choose not to use factory methods and just use the normal NSArray initializers. They are pretty much the same as the factory methods only you do the allocation yourself. An example of this might be:

NSArray * foo = [[NSArray alloc] initWithObjects:@"foo",@"bar",@"baz",nil];

Accessing The NSArray

Apple has provided us with many great methods for getting data out of an NSArray as well as information about it.  Here is a table of methods and their descriptions.

- (BOOL)containsObject:(id)anObject Returns true if a given object is found in the array, false otherwise
- (NSUInteger)count Returns the size of the array
- (id)lastObject Returns the last object in the array (the one with the highest index)
- (id)objectAtIndex:(NSUInteger)index Gives you random access to the array. Returns the object at a given index.

These are just a few of the accessor methods of NSArray and most likely the only ones you will need to use.

Searching The Array

If you are looking for the index of an object in an array, there is really only one method you need to use. That method is indexOfObject: . An example of usage might be:

NSString * f = @"foo";
NSString * b = @"bar";
NSString * z = @"baz";
NSArray  * myArray2 = [NSArray arrayWithObjects:f,b,z,nil];
NSInteger idx = [myArray2 indexOfObject:b];
// This would return 1 (since NSArrays are 0 - indexed)

This is much cleaner code than looping over the entire array to find an object. It’s probably more efficient too as Apple is pretty clean in how they code things.

Sending Message To Objects In The Array

Ok, so this is pretty cool.  Say you have an array of objects that all need to do something.  For example, an array of bullets, and you want all of the bullets to move forward one pixel. Rather than looping over each bullet object in the bullets array and calling [bullet move], you can do it in one method call on the array.  This method is called – (void)makeObjectsPerformSelector:(SEL)aSelector and here is an example of usage.

// Lets pretend the bullet object has a method called move
// and there is an array of 50 bullets
 
[bullets makeObjectsPerformSelector:@selector(move)];
Advertisement

And that’s it… The move method will now be called on every bullet object in the array with this one method call. Very clean and easy to use. Now, if the method you want to call takes an argument, there is the – (void)makeObjectsPerformSelector:(SEL)aSelector withObject:(id)anObject method. This will allow you to pass an object to each method being called.

Sorting Arrays

Apple has provided us with some very slick ways to sort an NSArray. I will not go into too much detail here as I have a full tutorial planned dedicated to sorting arrays. For now, I will just show you how to sort an NSArray of NSStrings. The method we will be using is sortedArrayUsingSelector. Here is the example usage.

NSArray *sortedArray =
    [myArray2 sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
    // This will return a sorted array that looks like [@"bar",@"baz",@"foo"]

You can plug in any of the string compare functions there to compare the strings. If you are sorting an NSArray of custom objects (like users), you can overwrite the compare method for that object and pass compare in for the selector. Just make sure you remember the : at the end of the method.

Looping Through Arrays

So if you are reading this, I assume you have seen a for loop before. ex: for(int x=0; x < … This would most likely not be a good way to enumerate an NSArray as Apple has provided a much nice way for doing so. There are some situations where this method would be preferred (like when u need to calculate the indices or something). But in most cases, you will want to use the special for loop provided by Apple. If you have ever coded PHP, it is much like the foreach loop. Here is an example:

for(NSString * myStr in myArray2) {
    NSLog(myStr);
}

This will loop over myArray2 and pring each element in that array. Very clean and efficient.

Saving Arrays For Later

There is an Array of ways to save data on the iPhone (Pun intended). One way is to simply dump the array to a file. This will write out the NSArray to a plist file on disk that can be loaded later using the arrayWithContentsOfFile method of NSArray. That method is rightfully named writeToFile. The example usage for it is as follows.

NSArray  * myArray2 = [NSArray arrayWithObjects:@"foo",@"bar",@"baz",nil];
[myArray2 writeToFile:filePath atomically:YES];

And there you have it! You are probably wondering what the atomically variable means. Me too… Just kidding. If YES, the file will be written to a temp location and then renamed to its final destination. This is put in place to guarantee that the file won’t be corrupted even if the system crashes (rename will be much faster than write). Why is this needed you ask? Consider this scenario.

You want to write a huge array to disk to save it for later. When your app starts it checks the disk to see if this file exists, if it does it loads an NSArray from it. If it doesn’t it creates a new NSArray. Say the last time the app ran, the system crashed while the file was being written. If atomically was set to NO, the original file would be corrupt and now the application would be loading corrupt data every time it starts from now on (most likely causing a crash). However, if you set atomically to YES, the temp file would get corrupted and the app would never see it. That way, the next time the app starts it will create a new fresh NSArray and all will be good.

Good rule of thumb, set atomically to YES.

That concludes our tutorial on NSArray. If you have any questions or comments, feel free to post them in the comments section or write me on twitter.

This entry was posted in iPhone Articles, iPhone Programming Tutorials, iphone and tagged , , , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

23 Comments

  1. J
    Posted August 26, 2009 at 1:33 pm | Permalink

    Thank you for this excellent article! I really like short and concise reviews of basic objects. It gives me a fast high level view of a complex topic. It also affirms my existing knowledge while at the same time teaches me new things.

    Way to go! Please keep up the great work.

  2. Dave
    Posted August 26, 2009 at 3:58 pm | Permalink

    Nicely said J.

    Thanks Brandon!

  3. Brad
    Posted August 27, 2009 at 5:59 am | Permalink

    Good article… Didn’t realize you could do that “fire a method on all objects in this array” thing! Very useful!

  4. Scott
    Posted August 27, 2009 at 1:37 pm | Permalink

    Wow, I didn’t know about the selector either… that terminology finally makes sense!

    P.S. The write array method was also new to me, appreciate your article!

  5. Posted August 27, 2009 at 3:23 pm | Permalink

    Could you explain predicates as a way to search an array ?

  6. iPhoneLedger
    Posted August 28, 2009 at 12:16 pm | Permalink

    This is brilliant! You explained in such few words what I was trying to understand by reading volumes. Keep up the good work and keep posting Objective-C tutorials!

  7. Shane
    Posted August 29, 2009 at 8:45 pm | Permalink

    Excellent as always. Thanks.

  8. Posted August 30, 2009 at 4:10 am | Permalink

    Nice explanation, short and direct. You help a lot to us new developers.
    You rocks.

  9. Baskaran
    Posted August 30, 2009 at 9:59 pm | Permalink

    The tutorial is good – while the advertisement that appears is not. Some might argue – what is wrong – to me “Why would you show someone in Bra and Panties?”

  10. Posted August 31, 2009 at 10:24 am | Permalink

    @Baskaran Yeah, I appologize for that. The ads are randomly pulled every day from adBrite.com. We have no control over it. As I am typing, there is an ad for Manga, which is completely unrelated to our site. I will look into this.

  11. Posted October 16, 2009 at 3:37 pm | Permalink

    Honestly, reading this blog is much easier to understand than studying the reference book from the AppDev itself. Thanks for everything, Brandon!

    But i really need to know one thing….how do we connect an application to another? Like a view-based application to a utility based or something like that?

  12. Posted October 20, 2009 at 5:40 am | Permalink

    hello, how do i loop through an array in an xml?

  13. Posted October 21, 2009 at 9:50 pm | Permalink

    @Mia: the only way to *connect* two applications is using the URL schema, which will allow you to launch one application from another with parameters.

    Here is a good reading on this topic: http://bit.ly/YS49o

    Good luck …

  14. Junxuan
    Posted November 21, 2009 at 10:56 pm | Permalink

    hi,

    hmmm… how to create an object array? i mean adding objects to an array. the objects are the child of a class.. lets take the array of bullets for example.

    is it:

    NSMutableArray *bullet_array = [[NSMutableArray alloc] init];

    bullets_obj = [[bullet_class alloc] init];

    [bullet_array addObject:bullets_obj];

    Please advice.. thanks…

  15. Posted December 20, 2009 at 5:55 pm | Permalink

    exemplary work. You have gained a new reader. I hope you can keep up the good work and I await more of your excellent posts.

  16. Harry
    Posted March 10, 2010 at 4:34 am | Permalink

    float purchase = 1234.50f;
    float sale = 987.20f;
    NSNumber *purchaseObject = [NSNumber numberWithFloat:purchase];
    NSNumber *saleObject = [NSNumber numberWithFloat:sale];
    NSArray *array = [NSArray arrayWithObjects: date, nameField.text, purchaseObject, saleObject, nil];
    [array writeToFile:@"MyArray.plist" atomically:YES];
    // read a file
    NSArray *phrase2 = [NSArray arrayWithContentsOfFile:@"MyArray.plist"];
    NSLog(@”%@”,phrase2);
    RESULT MyArray.plist
    Root
    item 0 date 2010-03-10 12:21:33 +0200 >> show date only ?how to remove time
    item 1 string Harry >> ok right
    item 2 number 1234.5 >> would prefer 1,234.50 formatted
    item 3 number 987.2000122070312 >> would prefer 987.20 formatted.
    I would appreciate it if you could help me to convert the code. To look like the formatted version shown. Regards

  17. Posted March 18, 2010 at 2:41 pm | Permalink

    Cool post
    array functions have always been hard to get to undestand for me.

  18. PurplePain
    Posted March 26, 2010 at 10:38 am | Permalink

    Hi.
    I`m working around with the iPhone SDK and want to save my array data to an plist.
    I use the writeToFile method above.

    NSString *pfad = [[NSBundle mainBundle] pathForResource:@”Test” ofType:@”plist”];
    [personenDaten writeToFile:(NSString *)pfad atomically:YES];

    But nothing is written to my plist file. Even no error will occur.
    I have an array with three NSStrings and an plist with one array with three items.

    Any ideas?

    • PurplePain
      Posted March 29, 2010 at 5:22 am | Permalink

      So, I dif find out that he`s saving them temorarely, so I can use them aus long as I don`t switch the phone off. But he`s not saving in the plist.

  19. Simon
    Posted March 28, 2010 at 9:31 am | Permalink

    Terrific primer on arrays.
    Many thanks.

  20. smaeung
    Posted April 8, 2010 at 6:27 pm | Permalink

    That is cool essential tutorial about NSArray.

    Thanks
    smaeung

  21. hanshn
    Posted April 16, 2010 at 2:15 am | Permalink

    I think it is a very good arcticle.

    Is it posible to have a structure (ex. name, adress, po-no, and so) in the array ? And if it is how to write to and read from file. I have search but i can’nt find a solution.

  22. Posted July 17, 2010 at 2:14 am | Permalink

    Sir,
    In my project i have used a counter which increments the integer value when i clicked the movie button.Actually i have played a movie from server and i want to know that how many time from each user watch this movie.
    so when i click the movie button the counter value increment and automatically saved into plist.and now i want to read the data automatically from plist into server.so please help me.i have never worked on server so please give me a full detail about this.

    Thanks and Regards,
    IHSAN ULLAH KHAN

3 Trackbacks

  1. By Objective-C Tutorial: NSArray | iCodeBlog | IPhoneMate on September 27, 2009 at 3:40 pm

    [...] more here: Objective-C Tutorial: NSArray | iCodeBlog Share and [...]

  2. [...] Objective-C Tutorial: NSArray Tuto Objective-C sur NSArray [...]

  3. [...] the success of our las API tutorial on NSArray, I thought I would do another walkthrough, this time on UITextField. I will be explaining all of [...]

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">