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:
Nov 14

I’m writing this quick little tutorial because I could not find a single source for what I wanted to do, but found myself reading multiple docs and putting it together. So, here we go:

Having Return Execute an Action for an NSTextField

Part 1: Quick Setup

  1. Create a new Cocoa Application named TextFieldTutorial. (I am not going to go into much detail about this, as there are better beginning tutorials out there if you need it).
  2. Open your MainMenu.xib and create your UI. Create two NSTextFields one for input and the other for output. Set these up visually however you’d like.
  3. Add a new File that extends NSObject and name it TextFieldTutorialController (be sure to generate the .h file as well).

Part Two: Writing the Code

There are a couple set-up things we need to add to the code. We’ll need to add the references to the two NSTextFields in our controller’s header file. Make sure these are tagged by IBOutlet to allow Interface Builder to know that it can hook into it.

Additionally, create the method definition for hitting enter. You code should look something like:

#import <Cocoa/Cocoa.h>

@interface TextFieldTutorialController : NSObject {

IBOutlet NSTextField* inputField;

IBOutlet NSTextField* outputField;

}

-(IBAction)userHitEnter:(id)sender;

@end


Next, all we have to do is fill in the body for userHitEnter. It will be a rather simplistic method:

@implementation TextFieldTutorialController

-(IBAction)userHitEnter:(id)sender {

[outputField setStringValue:[inputField stringValue]];

}

@end

Yep, that’s it. This is easy.

Part Three: Hooking Everything Together

Now, that our code is ready, we need to hook the UI to the controller. Go back to Interface Builder and add a new Object to your NIB file.

Interface BuilderScreenSnapz001

Change the type of NSObject to TextViewTutorialController:

Interface BuilderScreenSnapz002

Now, hook up the outlets of TextViewTutorialController to the two NSTextViews. Do this for both inputText and outputText.

Interface BuilderScreenSnapz003

Next, we need to set up our inputText object. First, we will set it to only call an action on Enter. Otherwise, we would be making a message call on every press of the keyboard (feel free to leave it like this if you want to experiment).

Interface BuilderScreenSnapz004

Then the last thing we need to do it set the Sent Actions selector of the Input NSTextField to our controller and select the userHitEnter method.

Interface BuilderScreenSnapz005

Interface BuilderScreenSnapz006

That’s it! Build and Run, and you should be able to type anything in the inputText area and hit enter, this will update the outputText.

TextFieldTutorialScreenSnapz001

Tagged with:
Nov 13

One issue with JSON that has caused problems both here at work and with Celery is the fact that a list of elements is defined by the number of elements. That is, if there are no elements it will be a NIL entry in the Dictionary, one element will return a Dictionary and multiple entries will return an Array. So, programmatically, you don’t know what you are going to get at compile time.

Fortunately, the WebService you are using is will documented… right? Secondly, you are only ever going to get 3 possible results: NIL, NSDictionary or NSArray. As such, you know when something is a list, and can handle these special cases. This is how I am managing it in Celery. If there are better ways, please, let me know.

If the WebService Specification says something might be an Array, I will also treat it as an array. If it’s a single element, I create an array and put that element into it. That way, my business logic only ever has to deal with one type (array).

id object = [dictionary objectForKey:@"key"];
NSArray* myArray = nil;
if([object isKindOfClass:[NSDictionary class]]) {
    myArray = [[[NSArray alloc] initWithObjects: object,nil] autorelease];
} else {
    myArray = (NSArray*)object;
}

Tagged with:
Nov 08

There are a number of things that Cocoa provides by default that is really great.

If I wanted to call a method after X seconds in Java, I would have to create some sort of Timer class, create an Interface that defines a callback method, execute the timer with some class that implements the interface, have the Timer execute a timer loop handling all the necessary threading code (Thread Pool, etc).

With Cocoa you call performSelector:withObject:afterDelay:

performSelector:withObject:afterDelay:

Invokes a method of the receiver on the current thread using the default mode after a delay.

- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay

Parameters
aSelector

A selector that identifies the method to invoke. The method should not have a significant return value and should take a single argument of type id, or no arguments.

See “Selectors” for a description of the SEL type.

anArgument

The argument to pass to the method when it is invoked. Pass nil if the method does not take an argument.

delay

The minimum time before which the message is sent. Specifying a delay of 0 does not necessarily cause the selector to be performed immediately. The selector is still queued on the thread’s run loop and performed as soon as possible.

Discussion

This method sets up a timer to perform the aSelector message on the current thread’s run loop. The timer is configured to run in the default mode (NSDefaultRunLoopMode). When the timer fires, the thread attempts to dequeue the message from the run loop and perform the selector. It succeeds if the run loop is running and in the default mode; otherwise, the timer waits until the run loop is in the default mode.

If you want the message to be dequeued when the run loop is in a mode other than the default mode, use theperformSelector:withObject:afterDelay:inModes: method instead. To ensure that the selector is performed on the main thread, use the performSelectorOnMainThread:withObject:waitUntilDone: orperformSelectorOnMainThread:withObject:waitUntilDone:modes: method instead. To cancel a queued message, use thecancelPreviousPerformRequestsWithTarget: or cancelPreviousPerformRequestsWithTarget:selector:object: method.

This method retains the receiver and the anArgument parameter until after the selector is performed.

Availability
  • Available in Mac OS X v10.0 and later.
See Also
Related Sample Code
Declared In

NSRunLoop.h

So, significant functionality is built into the main system allowing you to call an arbitrary Selector without any extra work.

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 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:
preload preload preload