Mom hates this Blog She really does…

10Mar/100

Not everyone is happy about this move

Fuck, somedays it sucks being an adult. Next Monday at 1:30pm, I take our cat to be put down. She's approximately 8 1/2 years old, diabetic, hates (and I mean hates with vigor) the vet and being boarded, doesn't like anyone else but my wife and I, pisses everywhere and throws up when stress is introduced... and we're moving to California in three weeks.

I feel fucking sick that while I'm getting my opportunity to go do what I've always wanted to do, it's going to cost a life to get there. She simply isn't going to handle the move nor does anyone want to adopt a diabetic, bitchy cat (or even to take care of her while we're gone). I reached out to all the alternatives but the answer, which I already knew, was always the same: it'll be impossible to find her a home.

So yeah, anyone know how to decline responsibility for the shittier parts of adulthood?

8Mar/100

Obligatory “I Have a New Job” Post

My first thought was to expound on my time in my last two jobs, how they got me to where I'm at now, and a series of events and their unlikely outcomes that got me a job at a high tech Silicon Valley company. I would pontificate on the struggles of my existence at my current employer, the desire to move forward and not downward... it would be my best attempt at artistic prose in a blog post.

No one really wants to read that crap.

Instead, let's just try the "super simple" approach. I have accepted a position at Apple as a Software Development Engineer. Which is a nice way of saying "Im in ur iPhone appz, fixin ur bugz" gdb and I are going to be very close friends, which is cool because I kinda like the guy.

I start March 29th, so in three weeks I get to say goodbye to the soupy mess that is Iowa and say hello to the tax-strange lands that are California. This all happens at an unbelievably fast pace so while I'm ridiculously excited, I'm also terrified about the next two months but don't have any time to think about it. The wife and I went from no lists to eight pages of "things that need done" in a matter of an hour. Fun!

So goodbye Iowa, with your seven bajillion feet of snow and endless corn... It's been fun for the first 33 or so years but it's time to try something new. I'll be sure to give both Arnold and Steve hugs for you.

9Feb/100

Executing blocks after a delay

http://code.google.com/p/nukethemfromorbit/source/browse/trunk/Classes/

NSObject-BlockExtension.h
NSObject-BlockExtension.m

It's missing one thing I couldn't quite figure out: how to cancel a block once it's been delayed. I use this design pattern all the time to coalesce expensive methods that may get called upon a lot:

  1. -(void) thisGetsCalledALot
  2. {
  3.     [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector( _theRealMethod ) object:nil];
  4.     [self performSelector:@selector( _theRealMethod ) withObject:nil afterDelay:0.5];
  5. }
  6.  
  7. -(void) _theRealMethod
  8. {
  9.     // Some expensive calculation thingie here
  10. }

but with a block, there doesn't appear to be a good way to reference it again when issuing a cancelPreviousPerformRequestsWithTarget:. If anyone has any thoughts on how to do it, I'd love to know.

Filed under: Cocoa No Comments
21Jan/100

Getting the current mouse location

This guy makes a great point. When it comes to developing software for the Mac...

If it's getting too difficult, stop and back up. You're probably going about it all wrong.

I found his site as he solves a problem that I've had for as long as I've developed QuicKeys: getting the current, non-flipped, mouse coordinates of the cursor. We've always had to do the NSScreen/calculation dance (or resort to GetGlobalMouse()... Carbon... ick) His solution is so friggin' simple it made me laugh out loud when I first saw it:

  1. CGEventRef nullEvent = CGEventCreate(NULL);
  2. CGPoint srcPoint = CGEventGetLocation( nullEvent );
  3. NSLog( @"srcPoint: %@", NSStringFromPoint( NSPointFromCGPoint( srcPoint ) ) );
  4. CFRelease( nullEvent );

And as he says, "Sure enough, it works!" Works for multiple monitors as well. No more walking lists of screens to find points inside rects for me!

Filed under: Cocoa, Programming No Comments
14Jan/100

Determining Password Strength

Someone asked on cocoa-dev the other day...

Is anybody aware of a reasonable algorithm or some code that can be used to test/check the strength of a password?

which caught my attention as this is something I've needed to have in the past. A reply pointed this person to a Windows program called KeePass (which has also been ported to Mac OS X but their quality check method is really messed up) that is open source and has some functionality for determining password quality.

Taking a peek at the code, it wasn't terribly complicated what they were doing. They first look at every character in the password, note if it's a special, upper or lower case, etc. Then they look at the character that immediately precedes it to calculate a "difference" factor. This difference is then divided by another value representing the total number of times a character has appeared in the password so far. This results in a running total for "effective length" of the password, which is then multiplied by the natural logarithm of the "weighted count" of the characters found to produce a score.

Playing with their algorithm, a single character password nets a value 4 while a reasonable (by my terms) password ranges from 50 to 75. An insane 32-character has-tons-of-weird-shit-in-it password weighs in at over 170.

So what does all this mean? Therein lies the rub... there is no definitive or official weighting system for passwords, only suggestions on ways to make computational analysis of a password difficult. So while you're free to use my Objective-C version of KeePass's algorithm, you will need to decide for yourself what the results mean.

If you have a better algorithm (or have ways to improve the KeePass algorithm), I'd love to hear about it.

Filed under: Cocoa No Comments
5Jan/100

Processing Info.plist for single-file tools

It appears that Xcode 3.2.1 is unwilling or unable to expand build settings into info.plist files for single-file (command-line tools) projects. All the Googling I did today says "Fuggetaboutit", although there appears to be several bug reports asking for it to be an option.

Big deal, you say. There's several applications that will do preprocessing for you. True, but none of them work with .xcconfig files. Or are simple. When a preprocessor requires its own markup language to do its thing, something's wrong. So here's my setup/problem and solution.

We have a global .xcconfig file named MasterVersionSettings.xcconfig that looks something like this:

  1. CURRENT_PROJECT_VERSION = 4.1.0
  2. ST_BUILD_NUMBER = 132
  3. PROJECT_COPYRIGHT = Copyright ©2009-10 Cool Company. All rights reserved.
  4.  
  5. // *****************
  6. // Some comments
  7. // *****************
  8. //THIS_DOES_NOTHING=like_the_goggles
  9.  
  10. // Used in SVersion.h
  11. // Declares a special C preprocessor define
  12. GCC_PREPROCESSOR_DEFINITIONS = $(inherited) $(GCC_PREPROCESSOR_DEFINITIONS) $(APP_VERSION_MODE)

and a Info.plist that looks something like this:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  3. <plist version="1.0">
  4.     <dict>
  5.         <key>CFBundleVersion</key>
  6.         <string>${CURRENT_PROJECT_VERSION} (${ST_BUILD_NUMBER})</string>
  7.         <key>CFBundleGetInfoString</key>
  8.         <string>${CURRENT_PROJECT_VERSION} (${ST_BUILD_NUMBER}), ${PROJECT_COPYRIGHT}</string>
  9.         <key>CFBundleShortVersionString</key>
  10.         <string>${CURRENT_PROJECT_VERSION} (${ST_BUILD_NUMBER})</string>
  11.     </dict>
  12. </plist>

If you're not familiar with .xcconfig files, they allow configuration of build-time settings outside the actual build settings for a project. Think of it as a global variables file for projects... this one file can be referenced by any number of projects (I have over 65 for this application) and ultimately saves buckets of time, especially when build numbers are changed.
http://developer.apple.com/mac/library/documentation/DeveloperTools/Conceptual/XcodeBuildSystem/400-Build_Configurations/build_configs.html#//apple_ref/doc/uid/TP40002692-SW7

For bundled applications (non-command-line applications), all one has to do to process the info.plist with these settings is to turn on INFOPLIST_EXPAND_BUILD_SETTINGS. For CLI apps, however, this doesn't seem to do anything. So we have to do the work of processing the file ourselves. Enter The Perl.

In your project, under Targets, right-click your application name, select Add -> New Build Phase -> New Run Script Build Phase. This opens a window in which to enter a script (we'll leave comments about how much this interface sucks for another day). Change shell to /usr/bin/perl and paste this code into the Script text area:

  1. #!/usr/bin/perl
  2. my $debug = 0;
  3.  
  4. # You may need to configure these to your environment
  5. my $xcconfig = join( "/", $ENV{PROJECT_DIR}, "../MasterVersionSettings.xcconfig" );
  6. my $source_plist = $ENV{PRODUCT_SETTINGS_PATH};
  7. my $processed_plist = join( "/", $ENV{TEMP_FILES_DIR}, "Preprocessed-Info.plist" );
  8.  
  9. print "Running info.plist builder...\n\n" if( $debug );
  10.  
  11. my %vars = ();
  12.  
  13. # Read the xcconfig file for key = value pairs
  14. if( !open( XCCONFIG, $xcconfig ) ) { die "Unable to open $xcconfig: $!\n"; }
  15. while( <XCCONFIG> )
  16. {
  17.     chomp();
  18.  
  19.     next if( $_ =~ /^\/\// );
  20.     next if( $_ =~ /^\s*$/ );
  21.  
  22.     my( $k, $v ) = split( /\s*=\s*/, $_, 2 );
  23.    
  24.     $vars{$k} = $v;
  25. }
  26.  
  27. close( XCCONFIG );
  28.  
  29. if( $debug )
  30. {
  31.     while( my($k,$v) = each %vars )
  32.     {
  33.         print "$k: $v\n";
  34.     }
  35. }
  36.  
  37. # Replacements
  38. my $eol = $/;
  39. undef $/;
  40. if( !open( SOURCE_PLIST, $source_plist ) ) { die "Unable to open $source_plist: $!\n"; }
  41. my $input_plist = <SOURCE_PLIST>;
  42. close( SOURCE_PLIST );
  43. $/ = $eol;
  44.  
  45. while( my($k,$v) = each %vars )
  46. {
  47.     my $pattern = "\\\${$k}";
  48.     $input_plist =~ s/$pattern/$v/g;
  49. }
  50.  
  51. if( !open( OUTPUT_PLIST, ">$processed_plist" ) ) { die "Unable to write to $processed_plist: $!\n"; }
  52. print OUTPUT_PLIST $input_plist;
  53. close( OUTPUT_PLIST );
  54.  
  55. print "plist has been created\n" if( $debug );

(available for download on Google Code)

Close the "Run Script Phase" window. Name the "Run Script" phase to something like "Build Info.plist" or something descriptive, then drag it above the "Link Binary With Libraries" phase. This is required as the actual inserting of an info.plist file into a single-file application is done at link time.

Finally, to stick your plist into your application, edit OTHER_LDFLAGS and set it to:

-sectcreate __TEXT __info_plist "$TARGET_TEMP_DIR/Preprocessed-Info.plist"

Build your project. Assuming you have no errors, your command-line app should now have the plist embedded into it. You can verify with otool or strings.

Filed under: Cocoa No Comments
20May/090

Is Blogging Dead?

Maybe for this blog...

Sorry I've not written much. Twitter is the new outlet all the hip-and-trendy kids are using these days and while I'm not a huge fan of the term "microblogging", it kind of fits. But only if it's 140 characters or less.

Actually, work has be crushed right now. We're on the fourth beta of QuicKeys and I'm averaging about 60 hours of work a week. That, plus all the volunteer web/membership duties for the Capital Striders. Plus trying to get some quality training runs in. And, oh yeah, the wife's still pregnant. Something had to give and blogging is the first to go. Video game time is down, too... haven't touched Guitar Hero in months.

There's tons of stuff I'd like to go more in-depth about concerning QuicKeys. And I'd love to discuss running more (and my current injuries) and waxing on about how feeling your kid kick for the first time is a little strange and pretty friggin' cool at the same time. And I'd love to actually play my copy of BioShock before BioShock 2 comes out.

But not right now.