Archive

Archive for the ‘Development’ Category

Writing private methods in Objective-C

January 8th, 2010

So there isn’t a real way to write private methods in Objective-C.

What I tried to for a while is to just write the methods in the .m file and simply omit the declarations in the .h file. This would be quite annoying when you call the private methods before they are defined in the .m file because Xcode would give warnings.

One convention we’re using to deal with this is to define a (Private) category at the top of .m file containing all the declarations of the private methods. By doing this, you’re letting the compiler know that  about the “private” functions that these functions will exist, so the warnings go away. It’s also a nice way to communicate to the readers of your code that the methods are private. The (Private) category is defined inside the .m file, so it really remains, well, private.

Here is a real example from our Say a Secret project:

#import “BadAssButtonController.h”
#import “ButtonUtil.h”
#import “Debug.h”

// Private methods

@interface BadAssButtonController(Private)

-(void) doneAnimating_;

@end

@implementation BadAssButtonController

@synthesize overlayImage;
@synthesize button;
… blah blah

If you enjoyed this post, make sure you subscribe to my RSS feed!

Development, Objective-C, iPhone Development

2010

January 8th, 2010

holy crap I just realized that 2 in binary is 010. 2 + 010 = 2010. Do you know what this means? It’s the end of the world of course.

Well, whatever surfing that I missed out on during the summer of 2009 because I was too busy cutting PNGs for Say a Secret ™, I’m doing it these days. I’m actually going out to Pacifica tomorrow. There are swells coming in, and the conditions are supposed to be good. I’m feeling even better because I got home about 30 minutes ago and fixed a bug (that I created a few weeks ago which went unnoticed) without too much hassle. All thanks to a small bit of reading I did over the summer.

The book is Cocoa Programming for Mac OS X. This book is badass. It filled all the gap in my knowledge about Xcode, Cocoa, Objective C in one schbang. Thanks Aaron, you’re awesome. Chapter 1 even ends with a little motivational section on “How to Learn.”

Besides the general badassery of the book, I want to point out one of the strongest aspects, in my opinion of course, of this book - it is very hands-on. It doesn’t try to sugar-coat with dense jargon or make you feel itty-bitty by using theoretical mumbo jumbo. It even tells you *gasp* how to debug. And it was what I learned from this section of the book on how to debug that saved the day.

We’ve all seen it - the cryptic stack traces you see in Xcode when things foobar:

2008-08-01 21:10:20.138 Tomatoes[151:20b] *** Terminating app due to uncaught exception ‘NSRangeException’, reason: ‘*** -[NSCFString replaceCharactersInRange:withString:]: Range or index out of bounds’
2008-08-01 21:10:20.213 Foobar[151:20b] Stack: (
808163835,
806099672,
807978623,
807978527,
812533155,
812164939,
812716685,
22067,
35325,
812317455,
812317325,
824032771,
824024301,
824022997,
807779567,
807777675,
829004012,
816177936,
816214500,
8381,
8244
)
terminate called after throwing an instance of ‘NSException’
kill
quit

I’ve seen some tips on how to decode this stack trace using ‘atos’ or whatnot. Guess what, I’m too lazy for that. I’d rather sprinkle NSLog statements than cut & paste some numbers around.

News flash! There is an easier way folks!

Step 1: From the menu go to Run -> Manage Breakpoints -> Add Symbolic Breakpoint, and add “objc_exception_throw”. Now you’re all set - your Xcode is now badassified to automatically break whenever you write crappy code that throws an uncaught exception.

Step 2:  Write crappy code and make your code crash. C’mon, you know how to do this.

Step 3: Run your code - when it craps out, you’ll see the ‘(gdb)’ prompt and your program has auto-suspended.

Step 4: Find that little spray can icon back in your Xcode IDE. It’s somewhere right above the editor.

Voila, now your see the stacktrace right in your IDE. No commandline incantation or nuttin. Now let’s go back to life & surfing.

If you enjoyed this post, make sure you subscribe to my RSS feed!

Uncategorized, iPhone Development

Extremely Useful Debugging

August 26th, 2009

More likely than not, your application will have crashed at some point in its development cycle. And you will have seen a cryptic message like this on the console.

2009-08-19 13:45:19.059 TestApp[3905:20b] Stack: (
2478641131,
2426342971,
2478670314,
2478663660,
2478663858,
92386,
816691521,
816216343,
816148479,
816144864,
827743722,
827753484,
2478142405,
2478144168,
827745792,
827745989,
816114848,
816160924,
9656,
9510
)

The problem is that you have no idea where in the code the crash is happening. Java’s stack trace is very descriptive, with function names and line numbers. This is also possible in XCode, but you have to take an extra step.

Run your iPhone application and then wait for it to crash, displaying the stack trace as above. The program will have paused at this point. If you go down to the console, you’ll see a prompt that says (gdb), where you can type in gdb commands.

Look at the stack trace above, and try to find a small number somewhere in the middle of the stack. This is likely where your program crashed. In the example above, this number is 92386. Once you have identified this number, you can now identify more helpful information about the crash.

Issuing the command: info symbol 92386

Will give you something like this:
-[MainViewController touchesEnded:withEvent:] + 164 in section LC_SEGMENT.__TEXT.__text of /Users/Min/Library/Application Support/iPhone Simulator/User/Applications/877EB45A-AB6B-4CD5-AA43-C7B0F2C98F7B/TestApp.app/TestApp

Issuing the command: info line *92386
Will you give something like this:

Line 416 of “/Users/Min/Documents/Projects/TestApp/Classes/MainViewController.m” starts at address 0×168b5 <-[MainViewController touchesEnded:withEvent:]+119> and ends at 0×16985 <-[MainViewController touchesEnded:withEvent:]+327>

So there you have it. You now know that the crash took place in the [MainViewController touchedEnd:withEvent:] message on line 416.

If you enjoyed this post, make sure you subscribe to my RSS feed!

Development, Objective-C, iPhone Development , , , , ,

Threads and Waiting

August 24th, 2009

Proper use of threads will do wonders for your program’s responsiveness. It will also do wonders in making your code harder to follow. What if you have a thread churning along in the background and you’d like to know when that thread has produced a value before continuing on with your work? Maybe you have a thread called ComputeWinningStockThread that takes all the data from the stock market, applies some magic formula and spits out stocks that are going to make you millions in random time intervals.

1. Start ComputeWinningStockThread in background.
2. Until ComputeWinningStockThread has picked a stock, continue checking to see if it has.

This is the poor man’s version. It is also called the busy loop or polling. And it uses up valuable resources that your iPhone could be using for other things.

The proper way to handle this is with the NSConditionLock. You can use NSConditionLock to have one thread wait for notification from another thread before continuing. Or, in other words, it blocks until a condition is met (hence, the name conditional lock).

In Objective-C, this is the gist of what you would have to do.

1
2
3
4
5
6
7
- (void) ComputeWinningStockThread {
    while (YES) {
        [myLock lock];
        winningStock = [self someSecretAlgorithm];        
        [myLock unlockWithCondition:0];
    }
}

Then maybe in another message, you are calling this thread to earn your millions.

1
2
3
4
5
6
NSConditionLock *myLock = [[NSConditionLock alloc] initWithCondition:0];
[NSThread detachNewThreadSelector:@selector(ComputeWinningStockThread) toTarget:self withObject:nil];
 
// This will block until it is unlocked in the thread
[myLock lockWhenCondition:1];
NSLog(@"I have a winning stock! %@", winningStock);

If you enjoyed this post, make sure you subscribe to my RSS feed!

Development, Objective-C, iPhone Development , , , , , , ,

Handling didReceiveMemoryWarning

August 20th, 2009

Predicting user behavior on the iPhone is difficult. One can never know how many pages of Safari someone might have in the background hogging up valuable resources. Every now and then, I get reports of our application crashing for no apparent reason. More often than not, it’s caused by the phone running low on memory. It’s amazing how little memory we have to work with on the iPhone. With Safari taking up 8 pages in the background, our application was crashing at mere 8 MB of memory usage.

Load Late and Lazily

Sometimes you have to sacrifice the snappy UI for a low memory footprint. It’s better than your application crashing. This means never preloading resources but waiting until the moment you need it. If your XIB (NIB) file has a lot of views, try separating them into multiple NIB files so that you can load it individually when you need it. When a view is not visible, the system will free it from memory.

- (void) didReceiveMemoryWarning

The didReceiveMemoryWarning message will be called when the iPhone is running load on memory. It is highly recommended that you override this message in all your view controllers and print out a simple debug message in it. Also, do not forget to call [super didReceiveMemoryWarning].

- (void) setView:(UIView*) view

If you receive the didReceiveMemoryWarning message, the setView message will be called with a nil parameter. It will be called to release the view if the view is not the active view. This is where you will want to release as much resources as you can, such as all your IBOutlet variables. Also, do not forget to call [super setView:view] or your application will crash.

Initialization

Once your view is freed, the NIB will be read back into memory when it is needed. This means the viewDidLoad message will be called again. So take care not to place initialization code that should only be initialized once per application in that message.

CLANG Analyzer

If you haven’t tried this tool already, then you are truly missing out. Check out this extremely helpful post by Jeff Lamarche, the author of Beginning iPhone Development. CLANG will analyze your code and give you a detailed report of problems your code may have, including memory leaks.

Also, If you’ve missed my previous post about the dangers of UIImage, you can check it out here.

If you enjoyed this post, make sure you subscribe to my RSS feed!

Development, Objective-C, iPhone Development , , , ,

Memory Management Pitfalls

May 21st, 2009

I thought that, for the most part, I was done with memory management after moving on from C/C++ to Java. But we all know that was not to be, so I’ve created this quick reference sheet for my own reference that some of you may find useful.

Pitfall 1: The order matters
Assume we have a setter method in some class.

1
2
3
4
5
6
7
8
9
-(void) setText:(NSString *)newValue
{
   if (newValue != text)
   {
      [newValue retain];
      [text release];
      text = newValue;
   }
}

The NSString that is passed into setText may be another NSString. So the value that is passed in must be retained, because we can’t have the memory freed until we are done with the class. We release text because it is being repaced with newValue.

Note that it is wrong the write the code above as

1
2
3
4
5
6
-(void) setText:(NSString *)newValue
{
      [text release];
      [newValue retain];
      text = newValue;
}

This is a due to a somewhat subtle case when text and newValue points to the same instance of NSString. By releasing text, newValue will also be released.

Pitfall 2: Using the dot (’.') notation incorrectly

self.text = newText

is actually a shorthand form of

[self setText: newText]

Thus, it will retain newText, increasing the reference count. Do not confuse it with how it works in a language like Java.

this.text = newText

is different from

self.text = newText

Because the first is a direct assignment and the second is actually a message call.

Pitfall 3: Not following the fundamental rules of reference counting
The fundamental rules are:
1. If you allocate, create or copy it, you need to release it.
2. If you retain it, you need to release it.

Consider the following snippet of code

SomeObject *newObject = [[SomeObject alloc] init];
self.object = newObject;
[newObject release];

newObject needs to be released to balance the retains. The first retain is in the alloc call, and the second retain is in the setObject (aka self.object = newObject) message.

Also, if you write something like this

self.object = [[SomeObject alloc] init];

the retain count will be at 2 because it is retained once for the alloc and one more time for the setObject message.

If you’d like to read more about memory management, here is another post that I wrote about the topic (I also talk about NSAutoReleasePool a bit here).

This wasn’t a comprehensive overview of memory management, but I hope it was somewhat helpful.

If you enjoyed this post, make sure you subscribe to my RSS feed!

Development, Objective-C, iPhone Development , , , , ,

iHappyBirthday 1.1

February 8th, 2009

Fix and a Solution

Thank you to everyone who has purchased iHappyBirthday. Reaction to iHappyBirthday has been quite positive. However, we’ve been receiving reports of random crashes. We actually know why this happens. In a previous, unreleased version of iHappyBirthday, we displayed an alert message to the user telling him or her that the system is running low on memory; and that continuing without freeing up memory may crash the application.

But we removed this message because according to our tests, the phone did not reach such a low level of memory that it would cause it to crash. However, iHappyBirthday 1.1 uses a little bit more memory than 1.0, and that seems to have pushed it over some threshold which is making it more prone to crashing. We are happy to say that we have solved this problem by drastically reducing the memory usage. We have submitted version 1.1.1 and it should be available soon for download. But in the mean time, please follow the workaround from our support page.

Technical Mumbo Jumbo: iPhone Memory Management System

I’m writing this for the benefit of other developers who may be facing similar memory problems. Or if you are not a developer and just happen to be a glutton for pain, then please read on. Our application was not using that much memory, but when other applications (like Safari) were taking up over 20 MB of RAM, it would cause our application to crash due to the phone running low on memory. The following were my observations while chasing down this problem.

When the iPhone runs low on memory, it will start freeing memory from background applications like Safari. But why then was our application still crashing? This was because the rate at which our application was using up the memory was greater than the rate at which the operating system was freeing up the memory. Ultimately, it comes down to this simple fact:

“Always minimize memory usage.”

It’s not very enlightening, but that’s the fact of the matter. Looking at the Activity Monitor in Instruments, I noticed that the memory used by Safari continued to decrease bit by bit over time as iHappyBirthday was running. And then eventually, Safari was entirely removed and all resources freed. However, if iHappyBirthday was too aggressive in its memory usage, even though the OS was freeing up memory, it could not outpace the rate at which iHappyBirthday was requesting memory. The result? Crash.

UIImage!

For version 1.1.1, the memory use was halved. It was achieved by not using the UIImage’s imageNamed message and by intelligently loading resources. It turns out that if you use imageNamed, the resources are cached into the memory and the iPhone does not do a very good job of releasing the cached memory. For version 1.1.1, imageWithContentsOfFile was used in conjunction with imageNamed. And for the most part, the caching was handled by the application rather than the iPhone SDK.

It was interesting to see how the memory management system behaves on the iPhone. And even more enlightening to learn about the pitfalls of using UIImage’s imageNamed routine. In fact, the documentation for this routine states,

“This method looks in the system caches for an image object with the specified name and returns that object if it exists. If a matching image object is not already in the cache, this method loads the image data from the specified file, caches it, and then returns the resulting object.”

But of course, I never looked at the documentation before using this. Had I looked at it, I could probably have avoided all this mess.

So always remember to RTFM!

If you enjoyed this post, make sure you subscribe to my RSS feed!

Development, News and Updates, iPhone Development , , , , , , ,

Getting SVN to work with SCM

January 9th, 2009

If you don’t have someone that you’re collaborating with in your software project, this post does not apply to you.  But then again, if you’re writing software and you’re doing it by yourself, your probably should find someone.  You can only lay so many bricks in your lifetime.  So go get yourself a teammate and come back to read this one.

Though zipping up your file and passing it back and forth with Gmail between your team member does the job, there are much better ways to collaborate.  Among the most popular are CVS and SVN.  My recommendation is that you set yourself up at www.assembla.com.  (Their recent  controversial bait-n-switch move will have to be discussed at a later time).  It’ll cost you $2 bucks a month/per project.  Dudes, there are more money under your couch so spare me the whining about the costs.  I’ve been using assembla.com and the SVN service alone is worth the cost.

Before going on, there seems to be myths floating around about Xcode’s SCM.  Here are some:

  • it doesn’t work
  • it sucks
  • its buggy

My partner is gonna hate me for saying this since he is one of those people that believes that SCM sucks, but I hereby declare that SCM works, and it works just fine.  At least with SVN anyway.

So, on to getting SVN set up with SCM then.

Step 0: Create a project. If you already have a project you want to import into SVN then by pass this step.  Otherwise, let’s create a dummy project for this tutorial.  Go to File->New Project, then click on Applications under iPhone OS from the left side panel.  Click on View-Based Application then the Choose button.  Type in the name of your project folder and click on Save. (I chose ‘Sandbox’)

Step 1: Set up your SVN repostiory and get its URL. This is simply a matter of cut-n-pasting the URL of the repository.  Go to Preferences from the Xcode menu and click on the SCM icon on top.  To add your repository click on the ‘+’ icon on the left bottom side and give your repository a name.  Cut and paste the URL of your SVN repository into the URL field.  The rest of the fields should be automatically filled in by Xcode except username and password.  Type the username and password in, and your setup screen should look something like this:

Step 2: Import your project. Navigate to SCM->Repositories.  You should see your repository you just set up on the left side panel.  If you already have files checked in, you should see them when you click on your repository.  Click on Import, and simply select your project folder, then click on Import button.  Voila, now your code is in the repository.

Step 3: Check out your project. Huh?  Why do we have to import a project we just checked in?  This is the part that confuses a lot of people.  If you are familiar with how SVN works, this might not come as a surprise to you, but once exported, we’re not going to deal with the local copy of the project any longer.  You can even delete it if you wish.  It’s even possible to check out your project back into your local copy, but we’ll just check out the code into another folder for the sake of sanity.  Click on SCM->Repositories, then the Checkout button.  Type in ‘Sandbox SVN’ as your project name and check out the project.  You’ll be prompted to open the project, open the project.

Step 4: Configure your project to your repository. We’re not done yet, we still need to let SCM know which repository we want to check our code into.  This step might seem redundant but if you have multiple repositories you’re working with then it could come in handy.  Anyways, navigate to SCM->Configure SCM For This Project.  At the bottom of the window you’ll see a drop down menu labelled ‘SCM Repositories.’  Choose your repository, and you’re done!

As you edit your code and add files to your code, you’ll see letters appear besides the files you edit.  The letters you see next to you folders/files mean the following:

U - The code in SVN has been changed and thus your local copy needs to be updated.

M - This letter indicates that the file has been modified locally.

C - There is conflict with your code and the code in the repository.

A - Files you’ve added but have not been checked into SVN.  They’ll be commited on your next commit.

A few gotchas you have to look out for:

  • Remove build folder if it was checked in. This will not only cause build problems when you try to build someone else’s code, but Xcode will complain when you try to Update or check in code:
  • Refresh your project.  Refreshing your project lets your know what you’ve changed and also what has changed in SVN.  This is pretty useful if you do this right before you check in code or update your project.

If you enjoyed this post, make sure you subscribe to my RSS feed!

Tutorials , , , , , , , , , ,

Let’s be Introspective

January 8th, 2009

As long as we are being introspective about the previous year, let us talk a bit about Objective-C’s introspection. Objective-C is a highly dynamic language (dynamic typing, dynamic binding, and dynamic loading).  It does a lot of things at runtime that other languages do at compile time.  This adds great flexibility. Of course, the trade off is that you lose the security blanket of the compiler helping you out as it looks for errors at compile time.

A practical way I’ve used introspection in an iPhone application is to dynamically assign a control I’ve placed on a view in Interface Designer to an Objective-C object in code.  Take for instance that I have a bunch of UIImageView controls on many views, and I didn’t want to go into each view individually and manually associate it with each of the IBOutlet objects. This can get tedious very quickly.

What you can do instead is use introspection. You can send a view a subviews message and get back an array of all its child views. And each of those child views will have subviews as well, etc. You can use introspection and send the isKindOfClass message to each of the controls on the views to check to see if it is an UIImageView control. Then you can assign these controls to the objects that you’ve defined. Of course, you could have used the custom tag number as well, but then you would have to remember to label all your controls with an unique tag.  It can potentially become a maintenance hassle.

Here is a quick sample code:

1
2
3
4
5
6
7
8
9
int counter = 0;
NSArray *subViews = [self.view subviews];
for (NSObject *item in subViews)
{
    if ([item isKindOfClass:[UIImageView class]])
    {
        myObjects[counter++] = (UIImageView *) item;
    }
}

If you enjoyed this post, make sure you subscribe to my RSS feed!

Development, Objective-C, iPhone Development ,

Learning to fly… once again.

January 1st, 2009

I’m learning Objective-C.

Yet another language to hurdle over to accomplish something.  It’s not exactly a lingua franca of programming languages though, given that its a language for Apple platforms.  It got me thinking - what’s the deal here?  Why do we have so many programming languages?  When is Neo (Keanu Reeves) of programming languages going to come to us and say “No” to all this shinaningan?  I remember taking CMSC330 when the professor told us that after completing the course, we should be able to learn a new programming language virtually overnight.   Sounded cool at the time, and to some extent that has come true - from Basic to Java and no less than a dozen programming languages in between, I’ve used them all and you get the general idea of how to program a cpu/memory/disk model computer after a while.  Once you go though several modern programming languages, what’s left to learn is pretty much the nuances and syntax of the new language.  I never thought to think to myself then, why do we even have so many languages?  Programming languages are both broad and deep topic but most of the discussions revolve around how to learn the languages but not creating new ones.  It seems to me that many of the programming languages are creations of heroic lunineries in the Industry.  Thank you, Guido, Bjarne, et al…

How dare you.  Who do you think you are, playing god with us mortal human beings?  It’s like having to learn French, Chinese, and Finnish (Objective-C) just to talk to the Machine.  It’s as if the incident at the tower of Babel had a recursive effect and now the punishment pervades even throughout the programming languages.  I should find a book called ‘How to program a programming language in 7 days’ from Amazon.com and make my own language contribute to the madness.  It’ll feature polymorphism, platform-independence, garbage collection, and a garage door. And you know what its going to be called - Neo.

I got a bit sidetracked there.  My original intent when writing this entry was to reiterate some of the most important things that one need to do when learning a new language.  These holy covenants must be obeyed..  Otherwise you’ll be the guy asking the stupid questions.

rule #1.  RTFM.

Do your homework and read the books.  The tutorials.  The other books.  If you by pass this step, believe me, you’ll be asking stupid questions.

rule #2.  Type it in.

Type the example code you find in.  DO NOT CUT-N-PASTE.  Something about typing it in that make you absorb the material.  It makes sense if you thiknk about it.  Programming is not reading a novel.  You’re gonna be doing it afterwards.  Get your hands dirty fast, even if it means just mindlessly typing it in.

rule #3.  Ask stupid questions.

You’ll have questions.  Find a guru and start bothering him/her.  If you ask enough questions, you will inevitably ask stupid questions.  You’ll know you’ve asked a stupid question if the answer you get is RTFM.  Well, you know what to do then, repeat step #1.

If you enjoyed this post, make sure you subscribe to my RSS feed!

Development , , , ,