Archive

Archive for the ‘Objective-C’ 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

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

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 ,

Of Semantics

December 17th, 2008

Java Vs. Cocoa Framework
I think people have a tendency to get confused when learning a new language due to the difference in terminologies.  Often, we already have a conceptual knowledge of the topic, but the different terminologies confuse us.  Whenever you get confused, just refer back to what you already know.

Delegation Pattern
For example, the Cocoa Framework makes extensive use of the delegation pattern.  This is just a common design pattern and you should not be so hung up on the terminology itself, but rather keep in mind the idea behind it.  You have probably used it countless times in Java.

Where in Java have you used it?  See if this looks familiar.

1
2
3
4
5
Student students[] = new Students[3];
students[0] = new Student("John", "Doe");
students[1] = new Student("Cindy", "Barker");
students[2] = new Student("Mandy", "Moore");
Arrays.sort(students, new NameComparator());

In the Java code above, you delegate the work of comparing the names to the class NameComparator.  So NameComparator is a helper class.  This design pattern is pervasive in the Cocoa and Cocoa Touch framework.  What often ends up happening in Cocoa is that a certain task is delegated to a class, and this class conforms to a certain Protocol.

Protocol
Once again, if you are a Java programmer, you are already very familiar with this.  Just like Java, Objective-C does not allow multiple inheritance, but it does allow you to implement multiple interfaces.  Protocols are what interfaces are in Java.  The only catch is that unlike a Java interface, you do not have to implement each function in the interface.

Delegation and Protocols work together in tandem in the Cocoa Framework.  You delegate something to a class, and that class conforms to a certain protocol.

Once again, this is exactly the same as the Java example above. The NameComparator class conforms to the Comparator interface.

1
2
3
4
5
6
7
class NameComparator implements Comparator
{
    public int compare(Object obj1, Object obj2)
    {
        ...
    }
}

Then the work of comparing the two values is delegated to this new class.

It’s really simple, but simple ideas tend to sound confusing in your head when new terminologies are introduced.

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

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

Free Me from Your Shackled Embrace!

December 15th, 2008

The Problem of Memory Management
Mac OS X Leopard introduced garbage collection, however this feature is missing on the iPhone. Therefore, it is still necessary to manage your own memory through what is known as reference counting.

Reference Counting or Retain Count
Reference counting is actually a very simple idea and has been around for a long time. However, it has a tendency to get tedious when a lot of objects and references are involved.

In Objective-C, every object has a retain count (or a reference count). When an object is created, its retain count is 1. When an object is released, its retain count is 0. When the retain count is 0, the object is deallocated and the memory is freed. As you can see, this is a very simple concept.

We can work through a simple example.

1
2
3
[sam alloc];          // sam has retain count of 1
cindy = [sam retain]; // sam has retain count of 2
[sam release];        // sam has retain count of 1

When the code finishes, sam still has a retain count of 1, so the memory will not be freed. This is because cindy is being clingy and not setting sam free. So in order for sam to be free, we need to release sam one more time.

1
[sam release];      // sam has retain count of 0

AutoRelease
But there is a problem. What if you have a function that returns a newly allocated string? Consider the method below.  

1
2
3
4
5
6
- (NSString)getName
{
   NSString *name;
   name = [[NSString alloc] initWithFormat:@"Robot No. %d", 23];
   return name;
}

In the method above, name will have a retain count of 1 because of alloc and initWithFormat. And when we call the method (or send a message in Objective-C lingo), the caller would generally do this.

1
2
NSString *robotName = [self getName];
[robotName retain];

We retain the value returned by getName because we do not want the object to deallocate before we are done with it. However, this creates a memory leak because the retain count is at 2. We can call [name release]; inside getName right before it returns, but that would cause the retain count to go to 0 and the object would not exist anymore (because it would have been freed).

Meet the NSAutoReleasePool. We can modify the method above to:

1
2
3
4
5
6
7
- (NSString)getName
{
   NSString *name;
   name = [[NSString alloc] initWithFormat:@"Robot No. %d", 23];
   [name autorelease];
   return name;
}<span style="font-family: 'Lucida Grande'; line-height: 19px; white-space: normal;"> </span>

Take note of the line “[name autorelease];“. This line adds this object to the auto release pool. Meaning, the object will not be freed immediately, but rather sometime later in the future. All the objects in the auto release pool are released when the drain message is sent to the auto release pool.

Somewhere near the beginning of your code, you will have the line below.

1
NSAutoReleasePool *pool = [[NSAutoReleasePool alloc] init];

When the autorelease message is sent to an object, it is added to this pool. When [pool drain] is called, all the objects in the pool are sent the release message.

Remember
The thing to remember is that objects created with alloc, new, copy, mutableCopy or if any function is called that retains the object and increases the retain count, you will have to call a release for each one of those retains.

Any other method will have a retain count of 1, and the object will be added to the auto release pool so you don’t have to worry about those as long as the pool is drained.

Circular Retains
One final note of caution. You must remember to avoid situations where a circular link is created among objects when object A retains object B and object B retains object A. This creates a circular link and creates a retain cycle.

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

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