23. The power of for-loops in action

How are you feeling about for-loops? They making okay sense? I want to further drive the point home about how awesome they are by giving an illustration of a problem I faced recently. This post will be more of a quiz than anything else, but I feel like it will be useful.

Let me start by describing the scene. I was doing some OS X development (which is basically the same thing as for iOS as far as logic goes) and I ran into an interesting issue.

I had a window that I needed to be able to dynamically add subviews to. I needed to be able to hand this empty window an array of views, and have it lay them out display them correctly. To make the math simple, each subview in the array is 100 px tall and as wide as the outer window.

So if the array has one item in it when it is time to size the outer window, how tall is the outer container going to be? 100 pixels. So if their are 5 objects in the array, how tall does the outer window need to be? 500 pixels. Pretty easy.

The interesting part comes when you understand that the OS X coordinate system is opposite that of iOS. That means that (0,0) is on the bottom-left as opposed to the top-left like in iOS. To make things more interesting, I need to have the object that is at the 0 position in the array to always be at the top of the window.

If you think about it for a minute, can you come up with the basis for the logic we will need to put into this layout effort? We are definitely going to need a for-loop. Why is that? Well, we need to iterate through each view in the subview array and set it's y coordinate value to a certain position. This is easily achieved with a for loop. I'll go ahead and give you some basics to start off with:

Hopefully that isn't to hard to see what is going on. We are iterating through our array of view objects (NSView is the equivalent of UIView in OS X programming) and are using the setFrameOrigin: method to set the (x,y) values of each view we see.

We have everything in place to solve our problem. We don't need to worry about the x value, that stays the way it is. We do need to worry about the y value though. This is where the quiz comes in.

  1. Can you tell me what is wrong with the current code that is setting the y value like this: i * 100 ? Keep in mind, we want to have the object at index 0 be at the top of the view that originates from the bottom. And if there is an object at index 1, it needs to be below the object at index 0 in the view hierarchy, etc.
  2. What could we do (there are a few different ways of accomplishing this) to fix it so that our problem is solved? So that we are displaying our subviews correctly?
This type of exercise is a great way to evaluate your ability to reason through logical dilemas. Send me an email or leave a comment if you have questions or if you want to make a stab at the answer. I'll post the solution later on.

22. The for-loop

This topic is another one that took my brain a while to digest. The for-loop is an incredibly powerful and useful tool that you will find yourself needing/using all the time. It may be a little tricky to get the hang of at first but you can do it.

Let's start by recalling the situation we are in that necessitates the use of a for-loop. We need to build a big huge array and we don't want to build it by hand. To give you an idea of what I mean by hand consider this code:

Based on our exhaustive discussion that we have had on methods and method calling, can you describe what is going on here? We are calling the addObject: method on our srtrings NSMutableArray object. For each time we call that method, we are adding a string object into our array.

Based on this example, you can see how it would take a ton of work to build this array by hand. Lots of copy/paste and annoying editing. But the good news is that we don't have to do it that way! We can use a for-loop and our lives will be insanely easy.

Let's take a look at the structure of a regular (there are a few different variations) for-loop:

That's it. It doesn't look that bad, right? If you put that code into your app's viewDidLoad method, do you have any guesses what your console would look like? Let's talk about what is going on. After the for declaration, there are three separate components within the (), separated by ;'s. This is important syntax you need to get just right. We declare a local variable of type int name i that we give a value of 0. It's name and value can be anything you want. Standard convention (for whatever reason) is that you name it i, and we want 0 because that is where we start.

The purpose of a for-loop is to give you a control mechanism for-looping through some code a specified number of times. Based on our next condition i < 1000; how many times are we hoping this for-loop loops for us? from 0-999, or 1,000! Do you see how that works? This for-loop is looking awesome.

The final condition i++ does what the ++ command does everywhere else. It increments an int. So we start off our loop at 0, we make sure that i is less than 1,000, and if it is we run through the course of the loop, executing whatever code is in there, and after we run through once, we call i++ to say we have finished that round of looping.

The result is a useful tool that lets you easily control how many times to iterate over a specified bit of code.

So let's remember our goal of building this massive array of strings. Without me telling you what to do, can you think of how to put the pieces together and solve our problem? If not, that's ok. We will go over it. We want to declare the array once outside the scope of the for-loop, and then inside the for-loop we want to call the addObject: method 1000 times to build up the array. Check this out:


How cool is that?! You are going to love for-loops. They rock. Is there any part of that that isn't making sense? Can you see that because we are within the scope of the for-loop that we have access to the i integer? So at any point within the scope of the for-loop we have access to the iteration number that we are currently on. That number is called the index. Say that word 10,000 times over and eat it for breakfast. Index. Index. Index. You need to be able to use that word as interchangeable as your thumb. The index refers to the position in the array that you are currently at.

So let's tie up one last loose end before everything comes together and you will sit there in awe and wonder because of how useful arrays and for-loops are. We have just built our array of 1,000 strings, now what? How does that help us in our current project?

Remember I said the term index is very important. Whenever we hit the plus/minus button in our app, we are changing the value of a counter variable, right? This can be our index!! All we need to do is to set the label (the same code we already have inside of all of the if statements) to the value of the string that can be found in the array at index:count!

Try and figure that out. See if you can piece together the rest of this project. Are you seeing how cool this stuff is? Well, let me tell you, we are just getting started. The coolness will continue!

Ok, enough blabbing. Here is what I am talking about:

Assuming that we built our NSMutableArray as a global variable up in the viewDidLoad: method, we have access to both the array and the index variable we need, and the method objectAtIndex: goes into the array and returns whatever object is at the index position you are giving it. Pretty slick!

It is very important to know that your app will crash if you ask for an object at an index that doesn't exist. That is why I had the if statement there making sure that it wouldn't ask the array for it's 1001th object. We know it didn't have that many object so we aren't even going to ask!

Stay tuned for more goodness to come.

21. Arrays - A programmers best friend!

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.