Tuesday, March 30, 2010

EXC_BAD_ACCESS and Memory Management.

Hello,

I know I haven't said much for a bit, but I also have no followers yet, so hopefully none of them will mind too much.

I had to post this cause of how hilarious it is if you know what EXC_BAD_ACCESS means. This Apple Support discussion is between a few people who clearly know a bit about programming, and a bunch of people who really don't have a clue and don't particularly want one.

They are insistent that apple has a bug called EXC_BAD_ACCESS and they really need to patch it cause it seems to affect a lot of different programs.

If you don't see the significance of all this let me explain it a bit:

EXC_BAD_ACCESS happens when a program tries to change memory it does not have access to.

When you program for the iPhone, you use up memory by creating objects using alloc. Any time you create an object, for example

NSString *myString = [[NSString alloc] init];

the object gets a retain count of 1. See, objects in Objective-C / iPhone are sad individuals. They keep a little book of everyone who cares about them, well not a book really, just a count (retain count) adding and subtracting people (objects) as they are notified, and if their count ever gets to zero, they erase themselves. This way nobody has to tell the object to go away, they just tell it when they are done with it, and if everybody is done, the object gets erased, and the memory gets freed.

This is a great system, if you use it correctly. The problem is sometimes people forget to tell object they care (or don't care).

When you create an object with alloc, that means you care. The object gets a retain count of 1. (it sends itself a message [myObject retain]; . Now later on, if you send it a message [myObject release]; the object subtracts 1 from the list and offs itself. Memory freed.

If you create an object without alloc, for example myObject = [NSString stringWithString: @"Hello!"];

the object doesn't start out with that retain count. It is "autoreleased". This means it wrote it's name on a list (called the autorelease pool) and as soon as the run loop iterates (meaning within a couple milliseconds after your function was called and finished performing what it was supposed to do) everyone on the list (autorelease pool) gets a release message.

You can send these autorelease messages yourself if you want: [myObject autorelease] and your objects will get a release message unless somebody sends them retain.

So now let's say for example that you created a new object with alloc, and you didn't send it a
release message, then your variable went out of scope.
{
//anything that is declared in these braces goes out of scope when the braces end
NSString *myString = [[NSString alloc] init];
//myString is in scope here
}
//out of scope here
NSLog(@"%@", myString); //doesn't work.

Once you are out of scope, the word myString is meaningless. You don't have any way to access the NSString that you alloc'd anymore. The problem is, you didn't tell the string you had stopped caring, so the string didn't free up its memory.

Remember watching the matrix reloaded? I know, we've all tried to forget, but here's a quote: "Every program that is created must have a purpose, if it does not it is deleted."

So if you forget to tell an object you don't care, it won't be deleted, and eventually you'll use up all the memory, and your program will crash. This doesn't cause EXC_BAD_ACCESS though, that is a different problem.

If you instead create an object you do care about, but by some mistake, either not using alloc to create it, or sending it a release message too many times, the object erases itself. Then when you go to look for it it isn't there, but it's more than happy to haunt you cause you didn't tell it you cared: it causes an EXC_BAD_ACCESS. Then your program crashes, and you get no useful information on why it crashed from the error message.

So the moral of the story is: Tell them you care too much and they won't leave, (memory leaks) don't tell them enough and they haunt you when you go looking for them later on (exc_bad_access). This isn't the whole picture, I will go into more detail at some point, or if I get comments asking, but that's the general idea.

alloc retain count is 1
retain retain count is 2
autorelease retain count will drop by 1 after the run loop iterates
release retain count is 1
...
run loop iterates -- retain count drops to 0
object calls dealloc on itself, and frees the memory.

If you have the EXC_BAD_ACCESS error, search up how to enable zombies, it is useful in finding the source of the problem.

I'm forgetting... the point is that EXC_BAD_ACCESS isn't caused by apple, it is caused by the programmer. It isn't a single bug, it is many different bugs.

Peace

Sunday, March 14, 2010

Actions and Outlets

Hi Everyone,
Here goes, first tutorial, first iPhone app.

To make apps for iPhone you need to start by downloading Xcode, the apple provided programming tool. It is free, and if you have a relatively new version o
f OSX on your computer, you can even install
it from the CD instead. I'll leave that for you to figure out, there are instructions online somewhere if you get stuck.

Once you have it installed, it is time for your first app.

In keeping with programming tradition, I have to come up with some creative way to say "Hello World!" using an iPhone app.

Lets start with something simple. Open up Xcode, and choose File>New Project, pick iPhone OS Applications on the left, and pick View-based Application on the right.

Call this HelloWorld, and save it in a projects folder unless you really like a messy desktop.

Now we are presented with a stunning 13 files that are needed for this simple app.

Don't worry, most of them don't matter. Here are the ones I almost never touch:
  1. CoreGraphics.framework
  2. Foundation.framework
  3. HelloWorld-Info.plist
  4. HelloWorld.app
  5. HelloWorld_Prefix.pch
  6. main.m
  7. UIKit.framework
That leaves 5. the HelloWorldAppDelegate.h and .m files,
and the HelloWorldViewController .h, .m, and .xib files.

These groups of .h and .m files collectively represent a custom class. If you don't know what a class is, you may need a good book on Objective-C before we go too far with this, but you may not. Read on if you can learn very fast.

My favorite place to start is the .xib file, which is usually referred to as a nib file. I forget why that is. Double click on it and interface builder will pop open. If you don't see these 4 windows, you can get them from the Tools menu, (Inspector, Library) and window, (Bring all to front) and the one in the top center comes from double clicking on V
iew in the window at the bottom center.



Apple really did a good job with interface builder, you can play around with dragging things into and out of the window, they just drop in there and work. (Not that they do anything yet). Anything from the Inputs and Values group will at least sit where you put it, and if you save and close, (Command + S, Command + Q) then hit build and run in Xcode, they will be there in the window.

Let's start with a UILabel, and a UIButton.

Drag them onto the window, make the label say Hello World!, make the button say "Greet" or "Hello" or whatever you feel like, it doesn't really matter what it says. Here's mine:

Now save and close, (Command+S, Command+Q) and hit build and run.

If you have an iPhone or iPod plugged in, you may need to switch the top left picker from Device to Simulator.

There we have it, your first app.





No, not really, I was kidding, that isn't exciting at all. Now to make stuff work.

Now that we have these things in interface builder, the code needs to know about it somehow. That's where Actions and Outlets come from. Actions are really just functions, and Interface Builder tells your buttons and sliders to call them. Outlets are instance variables, and Interface builder assigns them when the nib loads.


So open up the HelloWorldViewController.h file. It should look remarkably empty and boring, something like this:

#import


@interface HelloWorldViewController : UIViewController {


}


@end




We want an instance variable to hold the label, so we can make changes to it. The normal way to declare an instance variable to hold a UILabel is to type in between the curly braces like below. We also want a method to be called so we can decide what to do when the button gets pressed. I used buttonPressed, with no return value (void) because a button doesn't need a return value.

#import


@interface HelloWorldViewController : UIViewController {

UILabel *helloLabel;

}


-(void)buttonPressed;


@end


We put a * in the declaration because the variable is a pointer to an object. This is fine if all we want is an empty pointer, but we want Interface Builder to connect it for us, so we put IBOutlet before that.

For the function, we tell Interface Builder about it with IBAction, and we put it in place of void.

Side Note: IBAction gets translated to void by the preprocessor when you hit compile. and IBOutlet gets translated to nothing.

#import


@interface HelloWorldViewController : UIViewController {

IBOutlet UILabel *helloLabel;

}


-(IBAction)buttonPressed;


@end


Now we can save this file and reopen the .xib file. In the main window (bottom center in my picture) click on File's Owner to select it. File's Owner is the Interface Builder representation of the HelloWorldViewController.h and .m files. With file's owner selected, click the Connections tab (blue arrow) in the Inspector window. You should see helloLabel under the Outlets section, and buttonPressed under received actions.




Next we want to connect these to the button and label. click on the little circle next to buttonPressed and drag over to the button. When you let go, a menu pops up with a lot of choices. We want touchUpInside, meaning they touched the button, and let go without sliding their finger off the button to cancel.


Next drag the helloLabel connection to the label. Once that is done, click on the label, and pick attributes on the inspector window (right) and slide the alpha to 0, making it transparent.


If you haven't guessed yet, I'm aiming to make the label appear when you touch the button. Now that the connections are set up, time for some coding. Save and close interface builder, and click the HelloWorldViewController.m. Here we need to implement the method we declared in the .h file.


@implementation HelloWorldViewController


-(IBAction)buttonPressed{

[UIView beginAnimations:@"showLabel" context:nil];

[helloLabel setAlpha: 1];

[UIView commitAnimations];

}



That's it. The first line is a repeat of the declaration, should be familiar if you know objective C. The next line is a class method to tell UIView not to make changes immediately, but animate them once we get to commit animations. since helloLabel is a UILabel, a subclass of UIView, it is able to check with UIView about when to make this change. Don't worry too much about how the animations work, they aren't the important part. The important part is making all these connections work together.

The setAlpha: command told the helloLabel to become visible.

If you build and run, this does what we want it to do, and makes the label visible.

Happy with that? I'm not yet, so here's an exercise to see if you understood:
Make the button also disappear when it is pressed, and make the Hello World move up to the center of the screen while it appears.

Hint:

helloLabel.center = self.view.center;

That's all for now, more soon.

Introduction

Hi Everyone,
I decided to make a blog about programming for the iPhone because I find it fun to pick up and learn a new language. Sometimes when things are going well I like to tell people, or show them how the programming is going. Usually though, what was a great victory for me looks pretty trivial if it was done well, so everybody very politely acts impressed, but really, it isn't that exciting for them.

Here though, maybe I will find some people who want to learn these things, or people who can teach me a few things too. I have no formal training, just a couple books I bought, Stack Overflow, and the vast libraries of the Mac Dev Center.

The Mac Dev Center - if you are not familiar with it - contains hundreds of helpful articles about all aspects of programming that will happily tell you that you should make sure you understand the meaning of life, the origin of the universe, general relativity, and what the hell happened in Syriana before attempting to read and understand the article.

Nevertheless, I managed to get this far, and I plan to learn more. I want to start from the top with something really simple, but not too simple. If you don't know anything about Objective C, I highly recommend Programming in Objective-C 2.0 by Stephen G. Kochan.

If you don't know the first thing about programming for iPhone, but you understand a bit about Objective C, check back soon and I'll start from the top.

Side-note: I have no intention of writing code for pre OS 3.0 iPhones, it seems like a waste. If you paid $699 for the phone, fork the extra $10 for the upgrade.

Up next: Outlets and Actions - Interface Builder First Steps.