Archive for January 2008


My (Real) Desktop

January 31st, 2008 — 1:56pm

It seems customary for people to post pics of their workspaces and Rands’ recent post has spurred me on to post mine. I’ve been spending this early part of 2008 clearing out my desk area so the timing is a bit serendipitous. I’ve finally packed away my old, dusty PC, which is now in the other room ready to be given to a friend. I’ve also installed a cable management solution which gets most of the cords and cables off the floor and (mostly) out of sight.

So, here it is (pics hosted on Flickr):

NoodleDesk NoodleDesk - Close Up

It is also in Rands “Pixel Rigs” group where you can find other people’s setups.

Some notes:

  • The cheese grater on the left is a PowerMac (2.3GHz DC). It is being retired in favor of the Mac Pro next to it. It was the machine I originally developed Hazel on. Will be looking to sell it so drop me a line if you are interested in it.
  • The monitor on the left was intended as the second display for the main machine but is attached to the old PowerMac for the time being.
  • I like large tabletops, but getting the second monitor cut me off from the left side of the desk. Real desktop space sacrificed for virtual.
  • There is a scanner hidden away behind the left monitor. It’s a very low traffic item so I don’t mind having to get up to get to it.

Additional pop-up notes available on Flickr.

By the way, this is my desk on a good day. Unfortunately, I haven’t ported Hazel to RL (real life) so my desk can accumulate quite a bit of stuff. With great desk space comes great clutter.

3 comments » | Noodlesoft

Happy Fun Leopard Bug Time: NSCalendar

January 25th, 2008 — 10:38am

Yes, folks, it’s Happy Fun Bug Time where I talk about what has been making me tear my hair out recently. In this installment, we talk about NSCalendar.

NSCalendar has a method called rangeOfUnit:inUnit:forDate:. What this method is supposed to do calculate how many of one time unit are in another. For instance, how many days are in a particular month. Since date calculations can get tricky, with daylight savings, leap years and all, this method is quite handy.

Or, it would be handy if it didn’t suffer from some pretty bad bugs on Leopard. At first, I tried something like the following to calculate the number of days in a given year:

  range = [[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit
                                             inUnit:NSYearCalendarUnit
                                            forDate:[NSDate date]];
                                  
  NSLog(@"%@", NSStringFromRange(range));

Given that this is a leap year, I’d expect “{1, 366}”. What do I get? “{1, 31}”. I suspect that wires got crossed with the days-in-a-month calculation. Oh, but the fun doesn’t stop there. Try this at home (kids: do not try this at home):

  NSCalendarDate          *date;
  int                     i;
  
  date = [NSCalendarDate dateWithYear:2007 month:1 day:1 hour:0
                               minute:0 second:0 timeZone:nil];
  
  for (i = 0; i < 365; i++)
  {
    range = [[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit
                                               inUnit:NSWeekCalendarUnit
                                              forDate:date];
    
    if (range.length != 7)
    {
      NSLog(@"Date %@ has week of length %d", date, range.length);
    }
    date = [date dateByAddingYears:0 months:0 days:1 hours:0 minutes:0 seconds:0];
  }

This cycles through each day of last year (2007) and calculates the number of days that week. Now, having just recently lived through that year, I think I can say with some certainty that no week had any more or less than 7 days in it. The above code prints out any oddballs. If you run it yourself, you find that quite a few days are in weeks exceeding 7 days. Upon closer inspection, you find that any day in a week straddling two months reports the number of days in the month, not the week. On weeks fully contained within a month, it reports 7 days. Again we are seeing a tendency towards the days-in-a-month calculation. Someone really likes computing that.

I've filed a bug report (rdar://5704940 for you Apple folks). Unless I'm doing something really wrong here or there were some time distortions last year that I was unaware of, you may want to avoid using NSCalendar's rangeOfUnit:inUnit:forDate: on Leopard for the time being. Thinking about it though, the time distortions would explain a couple weekends…

Update (Feb. 1, 2008):
I strongly recommend reading the comments. Thanks to Chris Suter for explaining what Apple's logic is in doing it this way. We all thought he was nuts at first but it appears that he was just explaining Apple's craziness.

In short, things probably are working as designed by Apple. I still think the design is flawed and that it is horrendous API. It seems that, in Apple's mind, Leopard is correcting a bug in Tiger (in other words, the intuitive and useful behavior in Tiger was a bug).

The original point stands that one needs to take care with -rangeOfUnit:inUnit:forDate:. It seems to be only useful for specific combinations of units and given the change in behavior between Tiger and Leopard, it becomes even more of a headache. If Apple is going to continue with this interpretation, then they should just treat these computations as undefined since the results are misleading.

17 comments » | Cocoa, Debugging, OS X, Programming

Idle Hands

January 8th, 2008 — 3:30pm

A common user annoyance is having alerts popping up at bad times. The worst is when the user is typing and focus gets stolen only to have subsequent key presses going to the new window, possibly resulting in the user inadvertently confirming something they didn’t want to. Peter Hosey discusses this particular case and outlines an NSAlert-based solution.

I recently submitted a patch for Sparkle+ to deal with a similar situation. It can be annoying to get an alert about a new version when you are working. A new version is not a “drop everything and deal with this now” type of alert. With this patch, when a new update is found, it will check the user’s idle time and hold off showing the panel until a certain amount of time has elapsed. This minimizes the chance of the user being in the middle of something when the alert comes up. Of course, this is only suitable for when the alert itself is not terribly critical or time-sensitive. It should not be used if it is in response to direct user action or if the alert is something that needs to be dealt with immediately.

Since this type of thing may be useful in other contexts, I’ve decided to generalize it and put it out there for your consumption. It’s a little NSObject category with two new methods: performSelector:withObject:afterSystemIdleTime: and performSelector:withObject:afterSystemIdleTime:withinTimeLimit:. The first will call the given method on the receiver when the user has been idle for the given period of time. The second method does the same but allows you to set a limit after which it will call the method regardless of idle time, thus preventing the method from being delayed indefinitely.

Beyond the use described above, you can use it in several other situations, such as doing some internal maintenance that may get in the way if the user is actively using the machine. You can reclaim/free memory, clear out caches, compact file stores, optimize data structures or whatever.

For the time being, I am using this in my Sparkle update alerts and my scheduled evaluation period expiration nags. What will be interesting is if this leads to some sort of “refrigerator light syndrome” where users notice that it only happens when they are not looking and are somehow bothered by it. Most likely, though, users probably won’t notice and, with any luck, they will be more receptive to the alerts when they do pop up. If that leads to an extra spring in their step, then I consider it a job well done.

The project is linked below. Make sure you read the Read Me file. If you end up using it, let me know.

Update (Jan 10, 2008): The original project had a couple files specified as absolute paths (so XCode wouldn’t find them). A new project has been put up with this error fixed. It is marked as version 0.6 in the package name and Read Me file.

performwhenidletest-0.6.zip

Update (Feb 5, 2008): It appears that the CGEventSourceSecondsSinceLastEventType() function hangs on Tiger systems. I have updated the code to check for the OS version and only do the idle delay on Leopard and later.

performwhenidletest-0.7.zip

I am also looking into patching this in Sparkle+. If you are using Sparkle+ with this feature enabled, drop me a line or wait for the patch which will hopefully happen soon.

12 comments » | Cocoa, OS X, Programming

Leopard ‘file’ command oddity

January 2nd, 2008 — 9:36pm

Apparently, Leopard changed the file command. On Tiger, the -i argument makes it print out mime types instead of the more human friendly descriptions it normally uses. On Leopard, this has been changed. From the man page: “If the file is a regular file do not classify its contents.” What this means is that a lot of files just get identified as “regular file” which doesn’t seem all that useful to me.

I found this change a bit reckless as it can break software using it (like a certain piece of software written by yours truly). I thought this might be a change that Apple inherited from BSD, but, doing a small survey (thanks to Tom Harrington for the FreeBSD datapoint), that may not be the case:

OS file version -i behavior
Darwin/Tiger (8.11.0) 4.10 print mime type
Linux (2.4.32) 4.12 print mime type
Darwin/Leopard (9.1.0) 4.17 do not classify regular files
FreeBSD (6.2) 4.21 print mime type

In addition, according to this man page which seems to describe the same version of file that is installed with Leopard, it also shows -i behaving like everyone else’s version.

So, the question is, “Apple, why?” It appears there are a bunch of other letters in the alphabet available. Why cannibalize an existing one?

In the meantime, I’ll just use the equivalent --mime option but I’m still a bit confused as to why I’m having to make this change at all. Bad Apple, no cookie for you!

Update:
Tim Buchheim points out in the comments that this new behavior is to make Darwin compliant with the Single Unix Specification. Now knowing what to search for, I dug up these release notes which list the changes (including the ones to the file command). Good to know that there was some reason for this.

3 comments » | OS X

Back to top