Get It Down

taking notes cause i'll forget

PSA: Property Shenanigans

What type of storage does this property use?

@property id thing;

Trick question.

It depends.

Pre-ARC and in GC it’s an implicit assign, post-ARC, but before Xcode 4.3 it’s not a valid declaration because explicit storage is required.

In Xcode 4.3+ with ARC it’s an implicit strong.

Now you might say to yourself:

“Well that’s a little convoluted, but I guess ultimately it makes sense. Strong is what you want most of the time.”

And you’d be right.

And if you used the ARC conversion tool, no big deal because it will do the right thing.

But, if you don’t use the ARC conversion tool, well too bad for you because you’ll get no warnings about this change.

AND… it’s completely undocumented.

I’m all for improvements, but maybe, just maybe, write it down somewhere.

I’ve filed a bug and as always appreciate dupes: Radar OpenRadar

Commitment Issues

ARC is one of most amazing advances in the history of Objective-C; really in the history of compiler technologies in general.

It’s really cool.

But….

We can’t all just make the jump right this second. No matter how good the ARC migration tool is, there’s a lot of code floating around and the time to migrate and retest can be insurmountable. An intermediary solution would be writing code that works equally well in ARC and non ARC projects.

Comparing to NSNull

Checks to NSNull come up a lot when dealing with things like parsing JSON and while it’s mostly just ==, there are some options.

The officially sanctioned method is NSNull sample code, but this will generate a warning in clang (BOOO HISSSS).

So here are the options as I see them:

- (void)someMethod
{
    NSString *aString = @"loremipsum";
    
    // This will complain: "Comparison of distinct pointer types ('NSString *' and 'NSNull *')"
    if (aString != [NSNull null])
    {
        
    }
    
    // This works (at least for strings), but isEqual: does different things 
    // for different classes, so it's not ideal
    if ([aString isEqual:[NSNull null]]) 
    {
        
    }
    
    // If you cast it to the class you're comparing against
    // then you're good to go
    if (aString != (NSString *)[NSNull null])
    {
        
    }
    
    // But we can also just cast it to id and
    // that works generically
    if (aString != (id)[NSNull null])
    {
        
    }
    
    // The thing that would be really cool,
    // would be [NSNull null] returning
    // id (like in the sample category below).
    // Wouldn't count on that one though.
    if (aString != [NSNull idNull])
    {
        
    }
}
@interface NSNull (idNull)
+ (id)idNull;
@end
@implementation NSNull (idNull)
+ (id)idNull { return [NSNull null]; }
@end

Casting to (id) seems like the simplest way to handle this one, so that’s the one I’m using right now.

Update:

One of my coworkers, @pgor, pointed out that he uses NSNull’s isEqual, which seems like a sensible enough thing to do. (I’m guessing Apple isn’t going to toss anything to screwy into an isEqual on an object that’s basically single purpose.)

if ([[NSNull null] isEqual:aString]) 
{
        
}

Also forgot to mention in the original post: it’s worth filing a bug against the documentation on NSNull to see what Apple’s official position is in this post static humiliator world we inhabit.

Radar

XXX Timestamps

Update:

Apparently there are half time zones, but the solution still stands since GMT isn’t one of them.


It’s pretty common to see a timestamp like this

2001-07-04T12:08:56-07:00

supplied by xml and json feeds.

I’m pretty sure this is because one of the relatively common date formats supported by Java is

yyyy-MM-dd’T’HH:mm:ssXXX

and as we all know, Java and the internet are besties.

Thing is, NSDateFormatter doesn’t know what to do with XXX time zone formats, because it’s based on unicode date formatting and XXX is ISO 8601.

Yay for standards!

Lucky for us we know two things worth knowing

  • there aren’t half time zones
  • time format string can escape segments with single quotes

so our date format string for our formatter becomes

yyyy-MM-dd’T’HH:mm:ssZZ’:00’

and we’re off to the races.

Everybody’s happy. Except possibly all those people writing Java.

(Insert your own joke about porn in the app store and XXX time, or maybe something about how our evil Cupertino overlords are censoring our time formatters!)