Feb 19

Ah, the most dreaded error. Your app crashes unexpectedly and the only output you have is EXC_BAD_ACCESS. Not a lot of information, and for someone from a Java or other higher level language background it can be very frustrating to track down. First of all, make sure you are running in debug mode always (even if you don’t have any breakpoints). This will give you a stack trace of what generated the EXC_BAD_ACCESS. Again, this may not actually tell you where the problem lies, because all EXC_BAD_ACCESS is telling you is that you are attempting to reference a pointer that is no longer valid. Therefore, at some point previous (unknown where or when) you blew away a pointer you shouldn’t have. Here are the three most common (in my case, at least) causes for these, and how to help mitigate or track them down.

Over Release – You’ve released an object, its retain count has gone to 0 and you try to access it. This is probably the most common thing that bites you when first starting out with Objective-C while learning how to manage memory. The stack trace will at least given you an idea of what object is over released (it may be an object owned by the one pointed to in the stack trace), and if you have designed your code well, encapsulation should keep you from having too many places to check. And trust me, encapsulation is key to minimizing the pain here, if you are throwing references around all over the place retaining and releasing, you are in for a world of hurt.

Once you have all the places that retain/release occur for that object, just make sure you have a one to one ratio. Apple provides a great Memory Management Document and is highly recommended. Pretty much, the gist of calling release is do it ONLY if you call retain, alloc or copy. That simple (but still easy to forget).

dealloc – This is one that bit me, and took awhile to track down. When you override dealloc on an object, remember to call [super dealloc] as this cleans up the object up the chain until it reaches NSObject and does the low level cleanup. When overriding, you need to release any objects you are managing as well. However, my biggest lesson learned here, is calling [super dealloc] LAST. I had called [super dealloc] before releasing my objects and started getting EXC_BAD_ACCESS errors. So, I spent multiple hours trying to track down a retain/releases inconsistency. Until finally realizing, that by calling [super dealloc] before cleaning up my objects, I had lost my reference to those objects.

stringWithFormat – If your stack trace is pointing to a bit of code where you are constructing a NSString via stringWithFormat, confirm that you are not trying to send a primitive (int, float, BOOL, etc) to %@. The runtime is attempting to access memory at a location of the primitive’s value. Let’s just say, I’ve done this more than once.

Those are the top three items that cause me grief with a EXC_BAD_ACCESS and the first three things I check when it appears.

Tagged with:
Aug 29

Love to be Notified! @ Dr. Touch. Good introduction to Notifications. Notifications are great, similar to a Publish/Subscribe network setup inside your application. However, Notifications are so cool, you may be tempted to over use them. Most cases your app will only have a single Object that actually cares about notifications. In this case, NSNotifications would be overkill and cost more than it saves, use Delegates.

Tagged with:
Aug 23

Wil Shipley has an interesting tip regarding semi-colons and implementation of methods.

End the definition lines on your method implementations with a semicolon, so you can copy-n-paste them to or from your header (or the “Private” category at the top of your file) as needed when they change. Semicolons are required in the “interface” section, but don’t hurt anything in the “implementation” section.

Tagged with:
Aug 16

KVO or Key Value Observing is a wonderful feature of Objective C and is implemented in iPhone. This allows any object’s properties be observed for changes from another object. This is amazingly powerful, without any coding on the observed object’s part, a controller may now know when when its value changes. You could set a flag to persist data to a database, update a widget on a UI, etc. All this can be done without having to set a event listener or notifications, etc.

To register an object to listen for an object’s values changing, use addObserver

XcodeScreenSnapz003

The object that is doing the observing must implement the observerValueForKeyPath method. This is the method that is called whenever a property changes on the observed object.

XcodeScreenSnapz004

That simple. For example, let’s say we want to add an object to a persistence queue on a change. Our PersistenceManager object (assume this exists) might listen to specific objects to change and add them to a queue to write to some storage when they do.

[someObject addObserver:persistenceManager forKeyPath:@"watchedData"
                                              options:0 context:nil];

Now, persistenceManager is listening for any change to “watchedData” of someObject. Next, we need to implement our callback method in persistenceManager.

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context
{
    if ([keyPath isEqualToString:@"watchedData"] == YES) {
        [storeQueue addObject:object];
    }
}

Unfortunately, all observed data come through the same method “observeValueForKeyPath”, so you’ll have to check values to determine the proper logic flow. There is an interesting discussion on properly handling this situation.



Tagged with:
Aug 14

From the iPhoneDeveloperTips Google Group

In your MyApplication_Prefix.pch file add these lines:

// DO NOT FORGET to add setting GCC_PREPROCESSOR_DEFINITIONS with
value DEBUG=1 to your target's debug configuration !!!!!
// DLog is almost a drop-in replacement for NSLog
// DLog();
// DLog(@"here");
// DLog(@"value: %d", x);
// Unfortunately this doesn't work DLog(aStringVariable); you have to
do this instead DLog(@"%@", aStringVariable);
#ifdef DEBUG
#   define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt),
__PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
#   define DLog(...)
#endif
// ALog always displays output regardless of the DEBUG setting
#define ALog(fmt, ...) NSLog((@"%s [Line %d] " fmt),
__PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
Tagged with:
Aug 14

Friendly reminder. If you register for a notification with the notification center, you must unregister on dealloc. If our object goes away, but is still registered to receive notifications, your application will crash.

Tagged with:
Aug 10

I’m a bit of a geek when it comes to coding standards. I have a perverse interest in seeing them implemented at places I am employed (although a totally lax attitude to actually enforcing them, go figure). I came across Google’s Standards Document for Objective-C. I found it a very interesting read, not only for setting some good standards, but also for giving some ideas of best practices. Best practices documents I crave, I so badly want an Effective C++ or Effective Java book written for Objective-C.

By the way, you’ll notice they are opposed to Dot Notation.

Tagged with:
Aug 07

I have to admit that one of the early confusions that I had when teaching myself Objective-C was figuring out dot notation. The dot (.) operator means VERY different things in other languages. Suddenly, in Objective-C 2.0 you can use it to access properties. This was just a source of confusion when reading through example code in the first day or two.

Big Nerd Ranch has a lengthy rant against dot notation. I have to admit, I’m not a huge fan of it, and tend to make use of brackets with set calls. But, he really doesn’t like it.

When I teach, I always make sure to mention the dot-notation addition to Objective-C 2.0. Then, I make sure to tell the students never to use it ever, ever, ever again.

He has a number of points, to justify this decision.

With Objective-C 2.0, we get dot-notation. Many programmers new to Objective-C like dot-notation, it reminds them of other languages that they are more proficient in. Except for dot notation doesn’t do the same thing in Objective-C as it does in other languages.

Which is exactly the issue I found myself in. I thought I understood what the code was doing, and then tried to use the operator as I understood it, and quickly found out that I was wrong.

So, while I don’t think I agree with the venom shown to dot notation, I do agree with the aversion to it.

Tagged with:
Aug 04

Starting to play with the Address Book on iPhone. One interesting caveat about the Address Book API is it written in C and makes use of Core Foundation (rather than Foundation).

Foundation vs. Core Foundation

Core Foundation provides the basis for Foundation. In fact, Core Foundation provides the basis for all Objective-C types under the hood. From the Apple Documentation we have the following table that defines all types that are shared:

Core Foundation type Foundation class Availability
CFArrayRef NSArray Mac OS X v10.0
CFAttributedStringRef NSAttributedString Mac OS X v10.4
CFCalendarRef NSCalendar Mac OS X v10.4
CFCharacterSetRef NSCharacterSet Mac OS X v10.0
CFDataRef NSData Mac OS X v10.0
CFDateRef NSDate Mac OS X v10.0
CFDictionaryRef NSDictionary Mac OS X v10.0
CFErrorRef NSError Mac OS X v10.5
CFLocaleRef NSLocale Mac OS X v10.4
CFMutableArrayRef NSMutableArray Mac OS X v10.0
CFMutableAttributedStringRef NSMutableAttributedString Mac OS X v10.4
CFMutableCharacterSetRef NSMutableCharacterSet Mac OS X v10.0
CFMutableDataRef NSMutableData Mac OS X v10.0
CFMutableDictionaryRef NSMutableDictionary Mac OS X v10.0
CFMutableSetRef NSMutableSet Mac OS X v10.0
CFMutableStringRef NSMutableString Mac OS X v10.0
CFNumberRef NSNumber Mac OS X v10.0
CFReadStreamRef NSInputStream Mac OS X v10.0
CFRunLoopTimerRef NSTimer Mac OS X v10.0
CFSetRef NSSet Mac OS X v10.0
CFStringRef NSString Mac OS X v10.0
CFTimeZoneRef NSTimeZone Mac OS X v10.0
CFURLRef NSURL Mac OS X v10.0
CFWriteStreamRef NSOutputStream Mac OS X v10.0

Because these types are actually the same, you can convert back and forth.

Toll Free Bridging

So, back to Address Book. It is written in C using Core Foundation (meaning it returns C types). This means that your Objective-C iPhone code is going to have a mismash of C types when using some of the System level APIs (almost all System level APIs are written in C to reduce memory footprint).

You lose some of the features of Objective-C (you are really just working with C at this point). So, you need to make sure you check for NULL before using a returned type or you will crash. No message passing to “nil” here.

CFStringRef string = StringReturnedHere();
if(string != NULL) {
   PlayWithString(string);
}

However, not all is lost here, and you don’t have to go back to the scary C world if you don’t want to. You can, in fact, convert all these types into Object-C Foundation classes and operate them as you would if it was returned by an Objective-C API.

NSString string = (NSString *)StringReturnedHere();
[string doSomethingCool];

Toll Free Bridging allows you to type cast from one Core Foundation type to a Foundation type and vice versa. This allows you to work with Core Foundation APIs directly but treat the results as Foundation.



          
Tagged with:
Aug 03

One interesting thing to note about IBOutlet and their connection to Interface Builder. If the field being defined as an IBOutlet does not have an explicit “setting” method, either by manually writing it or by using @property and @synthesize, the route to connect the Nib’s definition to this field in the file is setValue:forKey. This method retains the field that is set as an outlet. Therefore, even though you didn’t retain the field anywhere in your code, you need to release it in your dealloc method.

So, I typically just make sure all outlets are properties.

Tagged with:
preload preload preload