
Let me take you back in time to when I was a senior in high school. I was taking a computer programming class from a math teacher that was incapable of speaking in terms I could understand. I literally couldn't understand anything he was talking about for the entire semester. He would just stand up and ramble on and on about crazy stuff that I had no clue about.
Throughout the course of the semester, I was basically able to master the basic variable types, printing messages, and if statements. That was it. I remember hearing people talk about these things called arrays. I had no clue what they were talking about but the sound of the word made me want to run for my life because it was just another layer of complexity that I wasn't ready to take on at that point.
As we begin our discussion about arrays today, I want to assure you that there is nothing to be scared about. In fact, by the end of this lesson, you'll be laughing at me for ever being intimidated by arrays. They are one of the most useful and pervasive objects that we can use in iOS development, so let's dig in deep and make sure we understand them!
Simply put, arrays are containers. Look up at the image I added to this post. Filing cabinets are a good way to envision what arrays are because filing cabinets aren't anything particularly interesting by themselves, but they become important and useful when you have things to put inside it! So think of an array like a filing cabinet for now. It holds things.
What does it hold?
A fine question. Without going too deep into particulars that don't really need to be discussed right now, there are a few different types of arrays. Apple has done a lot of work writing classes and making easy-to-use API's for different objects that make our lives as programmers a lot easier. The NSArray (notice the similarity in name to NSString) is just such a class. The NSArray is an array like any plain old C array, but Apple has beefed it up with lots of extra features and goodies that we really benefit from. So to go back and answer the original question, NSArrays can only hold objects. This is very important to remember. We can't stick primitive data types (ints, doubles, booleans) inside of an NSArray. We can stick objects in the array just fine. That is what they are made for.
I've mentioned before that there are a bazillion different types of objects that we can use in programming, and we can even make our own types of objects (which is where object oriented programming becomes very powerful) but what is the type of object that we have worked with that you're most familiar with? NSString! We are going to go ahead and make an NSArray object and fill it up with some NSString objects and show you how awesome we can spruce up our previous app.
NSArray is an object
Ok so it needs to be understood that the NSArray is an object. It is an object whose purpose is to hold objects. If this doesn't really seem that intriguing, I promise it will. Whenever we are dealing with objects, we need to remember that creating them is done a little differently than primitive data types. If you recall, with something like an int, we could just declare 'int i;' and all is well! We can begin assigning values to i immediately.
But with objects, it isn't so easy. When you make a string like this 'NSString *myString = @"hello";' you might think that the myString variable is 'hello'. That is what it is and that is it's value. That is basically true, but the funny thing about that little * we've seen a few times is that it implies that the myString variable isn't exactly that value but a pointer or reference to the address in memory of where that value can be found.
Wow. You still with me? This idea causes a lot of problems for a lot of people. To be honest, it isn't something that you need to really worry about all that much at the moment, but as we dive into understanding more about objects, it is important to understand that the variable name you see is usually pointing to a place in memory where the value you want can be found.
So an object needs to have a place in memory that it can live and store information about itself. A place to call it's own. Since this post is supposed to be about arrays, let's go ahead and make ourselves an NSArray:
NSArray *arrayOfStrings = [[NSArray alloc] init];
How does that look? Have we seen this alloc/init business before? You may have seen it already, but I don't believe we have talked about it. Understanding the importance of the above code is something I can't stress enough. Simply put, the alloc/init call makes room in memory for your new object and gets everything ready for first use. It is the literal act of building an object. There is a big difference between declaring the name of an object:
NSArray *array;
And actually building the object so that it can be used immediately:
NSArray *array = [[NSArray alloc] init];
Due to the fact that we are doing OO (object oriented) programming, and we are going to be using objects all over the place, it would be good to get used to the idea of using the above methods.
So thanks to the alloc/init code we now have a nice new shiny NSArray that we can use. Let's think in terms of the app we built in the last post. How can we optimize that app's logic to incorporate this new NSArray tool? When you think of the implementation of the logic we put into that app, doesn't something just jump out and scream INEFFICIENT to you? Yes. What is we didn't want to stop the incrementing at 10, but rather 100, or 1,000? Would you really want to make that many if statements? I've seen it done before, but trust me, you DON'T want to do that. We can use an array to solve this issue quite easily. But first we need to add data to our array.
In Objective-C (and the associated frameworks) you will see that there are often two different variations of the same object type. So where there is an NSArray there is also an NSMutableArray. Where there is an NSString there is also an NSMutableString. And so on.
This term mutable implies that the object type is editable, or that you have full read/write access to it. In the case of the non-mutable types, you can fill them up with existing data (like from a JSON/XML file or something), or you can add data in when you first alloc/init the object. But after you make it, you can't change it's contents. You can only read the objects in the array.
Other than that minor difference, they pretty much both act the same. So to use an NSMutableArray in this instance wouldn't cause any difficulty because you just add mutable to the class name and we need the ability to add objects anyway.
So, our goal is to optimize our last project we just worked on. Do you still have the code for it lying around? Our goal is to be able to handle up to 1,000 button presses, and not have it take several hours to do it. 1,000?! Even if we aren't using if statements like I'm suggesting, won't it take forever to build the array? Well, it can take forever, but it doesn't have to!
For our next topic, we will be diving into the for loop. An amazingly powerful tool that is really going to save our bacon.