Archive for September 2009

NSFetchedResultsControllerDelegate methods, main thread

I was running into some issues getting updates to my NSFetchedResultsController to update my UITableViewController. Yeah, I know, who hasn’t? Sheesh, where have I been these past few years. Talking to girls or something?

Anyways, I discovered something that was not entirely intuitive until I tried a few experiments.

The problem that I’m trying to solve is that I have data on my server exposed as JSON. When my iPhone application is running and ready, it opens an NSURLConnection to download the data, then (using the CoreDataBooks sample as an example) creates a new NSManagedObjectContext (addingContext) to process the inserts and updates. My controller registers an observer on this context, so that when it finishes and saves, the changes can be merged back into the main context. This fires off the NSFetchedResultsControllerDelegate method (whew) -(void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath;

Say that two hundred times fast.

Anyways, what I was finding was that new records were triggering the delegate method, but updates were not.

So… Long story short is that I was creating the addingContext and registering the observers from within the NSURLConnection delegate method -(void)connectionDidFinishLoading. The problem [I think] is that this is in a secondary thread. NSURLConnection implicitly creates a new thread in initWithRequest, so that it does not stop the main thread from processing user interactions. Somewhere in the documentation I noticed something about making sure that fetched results controller updates are done in the main thread [can't find it now].

When I move the code to create the addingContext and add the observer up before I create the NSURLConnection, everything works correctly.

The only complication is that I have to add a few more lines here and there to clean up memory in case of different connection states.

Sleep would be nice

It is extremely difficult to get a detailed understanding of NSError after two weeks of 6 hour sleep increments.

Just sayin.

fixing autospec

Right. Was running into issues getting autospec to run on both a clean install of rails 2.3.4 as well as a machine that used to run it fine.

After some fiddling and reinstalling gems, it now works.

gem install rspec # currently 1.2.8
gem install rspec-rails # currently 1.2.7.1
gem install autotest-rails # currently 4.1.0
gem install ZenTest # currently 4.1.4

I think I was missing autotest-rails. I had to reinstall ZenTest after that became available to my system, to make sure it installed correctly. There were no install error messages before, I think something was just missing in the background.

Forking a 32 bit ruby process from 64 bit

Ran into an interesting issue on Twitter today. Turns out that the C headers for Quicktime are only available to 32 bit applications. This will make things difficult now that Snow Leopard is out.

I’m not sure if this is a good long term solution or not, but if your ruby is compiled such that it can run in either 32 or 64 bit modes (as it is in 10.6), you can fork a 32 bit ruby process from a 64 bit one.

This makes it possible to write a 64 bit wrapper for 32 bit code, so long as you can write it with forked processes in mind.

So, here’s a test to show the difference between 32 and 64 bit:

ruby -e "p ['foo'].pack('p').size"
8
 
arch -i386 ruby -e "p ['foo'].pack('p').size"
4

Now, the neat thing is that you can do this:

irb
>> pid = Process.fork do
?> exec("arch -i386 ruby -e \"p ['foo'].pack('p').size\"")
>> end
>> Process.waitpid(pid)

This will output a 4, exactly what we’d expect for a 32 bit process.

This would likely need a lot of work in order to incorporate into a project, but it’s encouraging to see work.

Update: @rbates just added this link to the README of his rmov gem (the gem that sparked this all off). I guess my idea isn’t completely far-fetched, as it’s the route Apple is taking with QuickTime itself. I still think it may be a viable approach in ruby, though it would complicate the code a bit.

I think that most of the complication would be in getting it to compile… if you’re creating a gem that requires compiling in 32-bit C headers, you’ll need to find a way to compile it into a 64-bit compile.

The second bit of complication would be in creating a messaging service that could fork a 32-bit process and receive coherent responses.

Hm… this might be interesting as a separate gem.

core data + ocunit, finally

6 hour train rides appear to be good for several things: reading, sleeping, drinking bloody maries and fiddling in XCode. The plus side is that I finally managed to get my unit tests to run against a real Core Data stack.

This wound up being a far more subtle and annoying problem than I was expecting, particularly since (as I very piteously wrote the other day) this seems so necessary as to be pervasive. Maybe everyone else skips this step out of frustration?

Continue reading ‘core data + ocunit, finally’ »

Don’t release unretained objects

Right. When you create a dictionary out of an NSString, you don’t have to release it, as it is not retained.

It’s one of those simple things that I keep forgetting: alloc, retain, copy and new are the keywords that generally mean an object had to be released. Otherwise don’t overthink it until you see a leak in Instruments.

Otherwise it goes into the autorelease pool? Or else it gets immediately released at the end of the present scope? Maybe this why I get confused; I’m used to languages where memory management is everything but manual, with all the benefits and problems that ensue. I suspect that the latter case does not exist, but can’t say definitively.

Core data + OCUnit = pain in ass

Finding more issues when trying to run unit tests against a Core Data stack. So far, I can’t get it to load the stack.

If I specify the URL from which to load the managed object model, I wind up with a nil string–the resource isn’t found in the bundle. If I try to get it to load the mom automagically, it appears to work but then can’t find my entity.

I’d think that since Core Data was the framework that got Apple to include OCUnit with XCode, there would be some documentation on how to do this.

Continue reading ‘Core data + OCUnit = pain in ass’ »

memory leak in UITabBarController?

Trying to figure out if the leak is actually in my code or not. It’s kind of bizarre… I don’t see anywhere that I allocate memory that I’m not taking care of later. I am doing something that doesn’t seem to show up in code examples, but it doesn’t seem like such a bad idea:

I have two view controllers in a UITabBarController. Since I share data between the two, I’m using an NSFetchedResultsController that I share between the two. Instead of just initializing a tab bar in my app delegate and pushing the view controllers into it, I’ve subclassed UITabBarController as my root view, and made it follow the NSFetchedResultsControllerDelegate protocol. So… when the fetchedResultsController gets updates, it should automatically update the other views.

The leak appears to be here:

self.viewControllers = [NSArray arrayWithObjects:navController, mapViewController, nil];

Not so apparent.

Hm… may put this one off for later, try to get some other functionality done and hope that this is a problem in the SDK that gets fixed with an update.

UPDATE: ignoring this for now. After hours of searching forums, I’ve found some references to similar issues. It’s a grand total of 256 bytes, and nothing I do in my controllers makes any difference. So… other people have file bug reports.

fix theme, or fix memory leak?

Hmmmm… tough call. The free wordpress themes out there are all… overused. Definitely need to customize one or build one out from scratch. On the other hand, I discovered a memory leak in the most recent edits to my iPhone application while on BART this evening.

It’s a sneaky one, too… not sure if it has something to do with the fact that I’m subclassing UITabBarController, whereas most sample implementations I’ve seen out there just create an instance of the base class. Maybe it’s assuming that I’m going to release some object that I haven’t noticed yet? Or, more likely it’s something in my code.

This is a job for… tomorrow.

passenger, GEM_HOME

Right. Big thing that I forgot. When I set up passenger on leopard, I had to run through a script that wraps ruby, so that I could import environment variables and such that otherwise get lost when passenger is started by apache.

#!/bin/bash
 
source /Users/sax/.bash_profile
exec "/usr/bin/ruby" "$@"

Then I use the PassengerRuby directive in the passenger section of my apache configuration.