2013-01-03

Pathological Core Data Database in iOS 5

I’ve spent far too long fighting with this bug today, mainly because Apple don’t appear to publish a list of the bugs they’ve fixed between iOS versions. And wow, their bug reporting tool is still styled after the 11 year old OSX Puma! There’s a design that says “we care about your bug reports”.

Anyway, here’s an example of a pathological Core Data database design that will crash iOS 5. It’s an obfuscated subset of the database I’m using in my current app:

pathologicalDB

Attempting to create an instance of “Entity3” and then set its “guid” attribute will crash iOS 5 every single time. What’s most annoying about this bug in the OS is that adding or removing an attribute or relationship anywhere in the object graph fixes the crash. The bug was silently fixed in iOS 6. There’s an example project here:

2011-10-12

Another Objective-C Gotcha - Synthesized Properties and Ivars

When synthesizing ivars and properties, Objective-C will give both the same name. Unless explicitly told to use the property by prefixing it with self., Objective-C will use the related ivar instead when referenced within the class.

I spent about two hours trying to track down the problem in the code below. It’s obvious now that I know what the problem is, but trying to isolate it from the rest of the application was tricky. The fact that the code in question was interacting with a block, a cause of much memory-related pain in the past, threw me off the scent for a while.

This is the interface for the class in question:


@interface Person : NSObject

@property (copy) NSString* name;

- (id)init;
- (id)initWithName:(NSString*)aName;
- (void)dealloc;

@end

This is the implementation:


@implementation Person

@synthesize name;

- (id)init {
    [self initWithName:nil];
}

- (id)initWithName:(NSString*)aName {
    name = aName;
}

- (void)dealloc {
    [name release];
}

@end

Here’s how we’d use it:


Person* bob = [[Person alloc] initWithName:@"Bob"];

NSLog(@"%@", bob.name);

This looks fine, but it contains a subtle bug. Trying to retrieve bob.name will result in a crash once the current autorelease pool has been drained. The synthesized property name and its backing synthesized ivar are both called name. When we set name equal to aName in the initWithName: method, we are setting the ivar, not the property. Thus, we bypass the copy logic that we’ve set up in the property and just change a pointer. The string literal @"Bob" is autoreleased, so we’ve got a pointer to a deallocated object.

There are two ways to avoid this mistake:

  • Always declare ivars explicitly, using a name that is different from the property name (ie. _name);
  • Always prefix property names with self. when referring to them.

2008-06-17

Woopsi Status Report

Woopsi progress is suffering at the moment due to my other commitments, but I’ll get back to it soon. I’m patching up bugs as they get reported in the forums, though, or if I spot any when I’m fixing other problems.

Two fixes today. First of all, the Screen class was still bitshifting left by 8 places instead of multiplying by SCREEN_WIDTH in its drag() routine. Although the bitshift is potentially faster, it’s a barrier to portability and I’m guessing that the compiler is smart enough to replace the multiply with a shift anyway.

Secondly, I noticed that the XOR dragging rect displayed when dragging a window could be dragged out of the parent screen if the screen had itself been dragged down. This is now fixed.

Both of these fixes came out of my search for an SDL bug identified by John in the forum (he’s managed to get SDL working with VC++, and documented the process).

Here’s something for discussion. Jeff notes that gadgets should raise “MOVED_FORWARD” and “MOVED_BACK” events when their z-order is changed. However, the z-order is controlled by the parent gadget. The only way to raise these events would be if the parent gadget called “child->raiseMoveForwardEvent()” or something similar when the order changed. This goes against the conventions in the rest of the system. Only the gadget should be able to raise events from itself.

The way around this is to expose the child gadget vector (or introduce methods for working with it, such as “getChildCount()”, “swapChildOrder(source, dest)”, etc) and allow gadgets to re-order their parents’ children. This means that each gadget can control how it re-orders itself instead of parents assuming that their children should all be re-ordered in the same way, and allows the usual way of raising events. It introduces other complexities, though. Thoughts?