views:

177

answers:

4

One feature of Java that I really like is autoboxing, in which the compiler automatically converts between primitives and their wrapper classes.

I'm writing a Core Data application in Objective-C/Cocoa, and I'm finding it frustrating to deal with my integer attributes programmatically. Here's why:

//img is a managed object that I have fetched

NSString* filename = [NSString stringWithFormat:@"image%d.png", [[img valueForKey:@"imageID"] intValue]];

If I happen to forget the intValue message, which I sometimes do, then the int that gets passed to stringWithFormat: is actually the pointer value.

The problem is that this happens totally silently--no compiler error or warning. Sometimes I'll spend way too long debugging when this silly, stupid thing is the problem.

Is there a way to change my programming style or my compiler settings to prevent me from getting caught in that trap?

Edit: I wasn't clear about the fact that the above example is just one of many places where I run into trouble. Here's another hypothetical example that doesn't have to do with strings:

Entity CollegeClass has two integer attributes: courseNumber and enrollmentLimit. Let's say I want to compare course numbers:

//classFoo is a NSManagedObjects I've fetched
if ([[classFoo valueForKey@"courseNumber"] intValue] < 400) {
    NSLog(@"undergraduate class");
}

Or similarly, suppose I want to compute the average enrollment limit for all the classes in the CS department.

+7  A: 

You can use %@ to convert a NSNumber directly to a string instead of the %d.

It will actually take any NSObject based class and convert it to a string I believe.

Aequitarum Custos
It will send `descriptionWithLocale:` or `description` to the object and use that message's result. For CF objects (including CG, etc.), it calls `CFCopyDescription` on the object. http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/Strings/Articles/formatSpecifiers.html#//apple_ref/doc/uid/TP40004265-SW1
Peter Hosey
Thanks for explaining the intricacies of it, I was unaware how it worked.
Aequitarum Custos
+1 This is a good idea for the string problem, but strings aren't my only issue. I edited the question to provide more examples.
Ellie P.
+3  A: 

This is only applicable when dealing with Core Data, but if you use MOGenerator to generate classes for your Core Data objects (which I'd recommend doing anyway), you can then use -[propertyName]Value methods to directly access the correct value for properties which return NSNumbers:

// These two methods are identical when called on a class 
// which was generated with MOGenerator
[[object imageID] intValue];
[object imageIDValue];
Matt Ball
I'd never heard of MOGenerator. That's a great idea, but I'm looking for something more fool-proof. The problem here is that I know I should be using intValue, but I sometimes forget.That would only work if I could use [propertyName]Value for all of my attributes, not just numerical data, and then re-train myself to always use that.
Ellie P.
A: 

Turn on the “Typecheck calls to printf/scanf” warning, if it isn't on already. This doesn't currently help with NS/CFString formatting, but I've filed a Radar enhancement request (x-radar://problem/7375186) for that. You're welcome to file your own, of course.

Peter Hosey
+3  A: 

… suppose I want to compute the average enrollment limit for all the classes in the CS department.

This is easy to do with NSArray's and NSSet's @avg operator. Of course, that will return an NSNumber, which puts you back in problem #2:

Let's say I want to compare course numbers:

//classFoo is a NSManagedObjects I've fetched
if ([[classFoo valueForKey@"courseNumber"] intValue] < 400) {
    NSLog(@"undergraduate class");
}

I assume you mean that the problem you risk is omitting the intValue message, thereby comparing the NSNumber object's id to the int.

The compiler offers a warning for such comparisons. In Xcode, add -Wextra to your “Other C Flags” build setting. For more warning options, see the full list of GCC warnings.

Peter Hosey
This is exactly what I was looking for. Thank you.
Ellie P.