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

Intel X-25M G2 160 GB SSD

August 28th, 2009

Solid State Disks (SSD) are the future! I hereby declare that if you own equities in Western Digital, Seagate or any other platter based hard disk company, you better sell it quick because they are in trouble!

The hard disk market has been the last remaining bastion of “new old-tech” that has not seen true revolution since the dawn of modern computers. By far, it is the slowest and the least reliable part of a computer. When I buy a computer, I know that I will more than likely end up having to replace the hard drive.

My new technology obsession is the SSD. The price has come down to a point where a mortal enthusiast can afford one now for a mere price of a leg (not the two like it used to be). With Snow Leopard being released, I decided to take my new SSD for a spin. The undisputed king of SSDs at the moment is the Intel X-25M. The second generation (G2) came out not too long ago. With absolutely no moving parts, zero seek time and insane random read/write speeds, this thing just screams along. Here are some videos.

Please excuse the shaky camera work and the horrible video quality. I was using my left hand to record (I’m right handed) and the video is from an old, antiquated digital camera that’s just teetering on death.

For the first video. I went into the Applications folder, selected bunch of applications, and opened them up all at once at the same time. This is a new video I made with Quicktime X’s screen recording feature — new in Snow Leopard. I felt compelled to make a new presentable video after getting way too many complaints about the horrible quality of the first video.

The second video shows me opening Adobe Photoshop, Illustrator and SoundBooth at once at the same time. If I had done this on a normal HDD, the HDD would have thrashed into tomorrow.

The third video shows boot time from a completely shut down state. The timer starts as soon as I press the power button. The stop watch is hard to see due to the darkness and my crappy camera, but you can catch a glimpse of the final time towards the end of the video. For this video, I made a makeshift tripod out of my chair a coffee table after receiving complaints about motion sickness.

The final two videos shows the boot up and program start up time from my old HDD. It’s painfully slow.

Program start up video from a regular hard disk.

I’m Sold!
After having only used this for a day, I can conclusively say that I don’t think I will ever go back to normal hard disks again. I believe that SSD is a revolutionary advancement in hard drive technology. When it comes to user interface performance, responsiveness (snappiness) and perception is everything. The number of IO operations per second this SSD can handle is impressive. It doesn’t matter what I throw at it, programs just load up in an instant.

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

Reviews , , , , , ,

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 , , , , ,

Tale of Search Woes

May 7th, 2009

I don’t know what has been going on (actually, I do), but we have been seeing a statistically significant increase in the sales of iHappyBirthday. It wasn’t too long ago that we noticed that our application would not appear in the search results if the search terms were “happy birthday”, though it was still search-able with the term “birthday”. It was odd because it has always been search-able by “happy birthday.”

We emailed Apple about it, and the response we got back was pure hilarity.

Search results are working as expected at this time. App Store search results are based on several factors determined by Apple-confidential algorithms.

I’m not sure what this super secret “Apple-confidential algorithms” were that made it unsearchable by “happy birthday”, but it at least it did make us laugh. It was most likely a canned response because search was actually broken.

Anyways, we didn’t realize how important it was for our application to be search-able by “happy birthday”, because as soon as search was fixed, our sales have doubled (albeit from a small number, but welcome none the less!).

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

News and Updates, Opinion ,

Back from the Dead

April 24th, 2009

It’s been very quiet here. Life has once again conspired to get in the way of our goals and dreams. My full time job has been keeping me busy at 70 hours a week. As much as I wanted to work on my iPhone project, I do enjoy what I do for a living, and one of my long term goals in life is to foster my career. Actually, allow me to impart some wisdom in light of the current economic crisis. I actually believe that investing in your career and education is the best investment that you can make (and not in retirement accounts, though it’s a good idea). I recently had my midterm as well, so that also kept me away from working on our second application.

The schedule is starting to regain some semblance of sanity, so I will be able to devote more time to the iPhone project once again. The lack of time is only part of the reason for the delay, however. We decided to totally abandon the current design and go for something more innovative and creative. I’m not actually sure how well it will be received, but we noticed that there are too many of the same old and tired interface designs on thousands of applications. Though our application might be interesting, we felt that the interface design may hold us back. So a paradigm shift in our thinking and a total overhaul of the interface was required in order to stand out from the crowd.

Wish us luck!

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

News and Updates ,

The Free Model

February 27th, 2009

We’ve received a couple of negative reviews due to the application crashing (which I explained in my previous post). I guess you can’t help that. But the good news is that we haven’t really heard of any more reports of it crashing after version 1.1.1 was published.

A couple of days ago, the Lite version of iHappyBirthday was released to the App store. Imagine my surprise when I checked the sales figure this morning and saw that it was downloaded close to 600 times. Only if the same were true of the paid version! I think we need to observe it a bit more to see what kind of effect the Lite version will have, but as of yet, it has had no effect. Hey, at least it didn’t have a negative effect!

We’re trying to implement one, last key feature to SaS before we release it to the general public. But it’s turning out to be a bit of a technical challenge. Hopefully it won’t hold us up for too long!

Edit: Oops. I miscalculated. It was downloaded close to 1000 times.

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

News and Updates, Opinion , , , , , ,