How to find that sqlite file behind your CoreData

This is a quick thing. Hard to find unless you know where to look. When running a CoreData driven app, there are times when you’d like to just rest your data store and start again. Doing a schema change is one such case. Of course if you’re doing something really silly and mess up the data, again.. reset!

So, to do that, simply delete the .sqlite file for your app. Running in the simulator, that is stored in your home directory under ~/Library/Application Support/iPhone Simulator/User/Applications/<special app id>/Documents/<appname>.sqlite

Easy, huh? Deleting this is sure nicer than clearing all apps and data from the simulator.

Finding freed/deallocated instances of objects

This procedure has saved me more than once, so I need to document it throughly for everyone! There are cases where I see messages (in the debugger console) that are like this;

-[NSFetchedResultsController class]: message sent to deallocated instance 0x11957d0

Sometimes, it will talk about “freed” instead of deallocated. That address at the end is important. To track down the line of code where the object was allocated, you’ll need to set a couple environment settings. To do this, right click on the executable you’re trying to debug and select “get info”. Select the “arguments” tag and set the values shown below;

 

debug environment settings

debug environment settings

(be sure to disable these when you’re done. They should not be enabled for a production build!)

Next, run your program and test enough to generate the error. In the Debugger Console, copy that hex address value, then type the command;

(gdb) info malloc-history <paste-address-here>

 

You should see something like this;

 

Stack – pthread: 0xa0416720 number of frames: 28

    0: 0x9264382d in malloc_zone_calloc

    1: 0x92643782 in calloc

    2: 0x93611618 in _internal_class_createInstanceFromZone

    3: 0x9361ab08 in _internal_class_createInstance

    4: 0x3020275c in +[NSObject allocWithZone:]

    5: 0x3020264a in +[NSObject alloc]

    6: 0x3d92 in -[AMRAPViewController fetchedResultsController] at /Users/dkavanagh/CrossFit Timer/Classes/AMRAPViewController.m:146

    7: 0x3a18 in -[AMRAPViewController viewWillAppear:] at /Users/dkavanagh/CrossFit Timer/Classes/AMRAPViewController.m:96

    8: 0x3097c945 in -[UINavigationController _startTransition:fromViewController:toViewController:]

    9: 0x30977c33 in -[UINavigationController _startDeferredTransitionIfNeeded]

   10: 0x3097d01e in -[UINavigationController pushViewController:transition:forceImmediate:]

The first line below the object alloc (in my case, line 6) will show where the offending object was allocated and should really help in tracking down the free/dealloc problem.

The original solution was posted in the app dev forums. You’ll need a login to see this.

Simple UIViewController Management

I’m writing a navigation based application for the iPhone and need to instantiate the same UIViewController (for a screen) in more than one place. In some sample code I’ve seen, local copies are kept in an NSArray. I’ve been doing that myself until I decided the Factory design pattern was probably more useful. I wrote the code below and it has been working very well.

#import <Foundation/Foundation.h>
@interface ControllerManager : NSObject {
NSMutableDictionary *controllers;
}
+ (ControllerManager *)controllerManager;
– (UIViewController *)controllerByName:(NSString *)name;
@end
#import <Foundation/Foundation.h>

@interface ControllerManager : NSObject {
	NSMutableDictionary *controllers;
}

+ (ControllerManager *)controllerManager;
- (UIViewController *)controllerByName:(NSString *)name;
@end

@implementation ControllerManager

+ (ControllerManager *)controllerManager {
	static ControllerManager *sharedInstance;
	@synchronized(self) {
		if (!sharedInstance) {
			sharedInstance = [ControllerManager alloc];
		}
	}
	return sharedInstance;
}

- (UIViewController *)controllerByName:(NSString *)name {
	if (controllers == nil) {
		controllers = [[NSMutableDictionary alloc] initWithCapacity:5];
	}
	UIViewController *ret = [controllers objectForKey:name];
	if (ret == nil) {
		Class cls = NSClassFromString(name);
		ret = [cls alloc];
		[ret initWithNibName:name bundle:nil];
		[controllers setObject:ret forKey:name];
	}
	return ret;
}

@end

If you’d like to push another view controller, do something like this;

[[self navigationController] pushViewController:[[ControllerManager controllerManager controllerByName:@"MyViewController"] animated:YES];

The first time the view loads, it is initialized from the nib. The nib must be named the same as the view controller, which by the examples I’ve seen is fairly common anyway. The view is then stored in the ControllerManager and served up as a singleton. Since you can write your view to load data before it is viewed, this pattern works well and saves memory by not allowing multiple copies of the views/controllers.

Using “autorelease” can really bite you!

This will be a short post, but there was a lot behind it. Trust me!

A few times, I’ve run into cases where my code didn’t run as expected. I’d initialize an object (sometimes in viewDidLoad()). Later, maybe in viewWillAppear(), or in a button delegate, I’d try to access that object and use it. The debugger would show an EXC_BAD_ACCESS. I’d step through the code and sometimes, the object would appear normal in the inspector. Other times, the debugger would think it was of a different type!?!

The cause, it seems was that when I initialized the object, I set autorelease, like this;

memberVariable = [[[MyObject alloc] initWithParam:param] autorelease];

I thought I was being smart by allow the object to be cleaned up for me. In fact, I was causing a problem because I apparently don’t understand the behavior of autorelease. It turns out it can cause objects to be released early. I would say avoid autorelease! It has bitten me several times now!

Dismissing keyboard for UITextField

I found it frustrating that editable UITextFields don’t automatically dismiss the keyboard when editing is done. I think this should be the default behavior, but what do I know?
First thing you need to do is implement the UITextFieldDelegate in your UIViewController.

@interface MyViewController : UIViewController <UITextFieldDelegate> {

The next is to set the controller as the UITextField delegate (I do this in the viewDidLoad method).

- (void)viewDidLoad {

	[super viewDidLoad];

	[myTextField setDelegate:self];

}
Then, implement textFieldShouldReturn in your controller like this;
#pragma mark UITextFieldDelegate

- (BOOL)textFieldShouldReturn:(UITextField *)textField {

	[textField resignFirstResponder];

	return YES;

}

The keyboard is the "first responder", and this causes it to go away when the "done" button is pressed (assuming you have a "done" button on your keyboard). Can anyone tell me why the numeric keypad doesn't have a done button??

iPhone development – tracking down uncaught exceptions

In the iPhone work I’ve been doing (my app), I’ve seen one error a number of times.. with various causes that were hard to track down. I’d see TERMINATED_DUE_TO_UNCAUGHT_EXCEPTION and never got a good stack trace. I found the solution in an iPhone dev forum (here) and thought I’d write this up to share the answer in case it saves someone some time.

What you need to do is set a breakpoint in objc_throw_exception. To do that, create a .gdbinit file in your home directory. Add the following to that file (I think the last line is the most important, but I have all of this in mine).

fb -[NSException raise]
fb -[_NSZombie release]
fb szone_error
fb objc_exception_throw

Then, bring up the debugger and run your app. Once you get an exception raised, the debugger stops where that exception is about to be thrown and you can see exactly where, in your code the problem originated! Big help to me, I can tell you! (Thanks, PhoneyDeveloper@iphonedevsdk.com!)