I'm working on an iPhone app right now, which mostly involves dev/test against the simulator, with occasional runs on a real iPhone to check everything is running the same there. But every time I flip that menu in the XCode toolbar from Simulator to Device and hit cmd-R I spend five minutes of confusion trying to figure out things aren't working even nearly right.

Picture 2
After a while and maybe a bit of debugging I'll get a hunch that all is not as it seems, I'll do a complete clean and rebuild and then my code will behave perfectly, with XCode whistling cherubically with an innocent look on its face. All that remains is for me to check the Build menu to reassure myself that cmd-R does in fact do "Build and Run" which it most certainly does.
I can only assume that there is a bug in XCode that doesn't correctly reset build state when switching between targets, so it thinks my build is up to date when in fact it's ancient.
I've done a lot of web development in my time and a lot of that time is usually sucked up in trying to make a site 'scale' well  - not in terms of dealing with vast quantities of users, but responding to changes in font size without the page layout going completely screwy.

Generally the user can change the font size on the fly to suit themselves, and as a page designer you really ought to cater to their whim. This means that you can't assume that your carefully setup sidebar links will always require just one line each, or that your box titles will always fit in the space available. It can be a nightmare to get right and if you have a very 'designed' page you often have to accept that it will only look reasonable within a certain font size range. Here's one of my blog posts unzoomed, looking handsome as always:

BrowserZoom1
I've noticed that web browsers have increasingly been looking to solve this problem without troubling the poor page designers. Safari 4 Beta and Firefox 3 now default to simply scaling the entire page rather than just the text, though you can select a "Zoom Text Only" menu option to go back to the previous behaviour. By zooming every last pixel of the page identically, page layout and design are kept together and in the originally intended proportions no matter what, though any images on the page may start to look a bit fuzzy as they get zoomed up beyond their native size.

Here's that same blog post of mine with text-only-zoom and then everything-zoom in Safari:

BrowserZoom2 BrowserZoom3
You'll notice that Typepad have done a really good job of making their site text-zoom friendly, and with everything zoomed (and not zoomed quite so much) the whole page is too wide to be usable. Horses for courses I suppose – there are going to be cases when each method is superior and hopefully users (ones that care about zooming at all) will be savvy enough to choose what works for them.
I sync my calendars across two Macs (desktop and laptop) using the horrifically named MobileMe. It mostly works fine (apart from the fact it often fails to sync some entries – a minor thing) but there is one irritation that's really starting to bug me.

Picture 1 
I get up in the morning and I wake up my desktop to read email and news over my Coco Pops, whereupon I often get some iCal reminders for the day – which I usually snooze to re-remind me later. Then at some later point I pick up my laptop and immediately after opening it up I get the same reminders (fair enough) and snooze them too. A minute later, after my laptop has synced I get a popup informing me of the clash of snoozed times, which I have to resolve and re-sync. I play this game all day, with sync conflicts ping-ponging between the two machines. It's completely ridiculous.
Picture 7
What would I prefer? Well I can understand the impeccable logic it's applying – it's just unfortunate the timing of events that leads to this result. How about the system always assuming that the last 'command' I gave is definitive and should automatically be applied without asking me on the other machines? Maybe I should email Steve, er Phil, and suggest it.
I've been writing some iPhone apps recently and have thus been re-exposed to the horror that is Objective-C. I've written plenty of Objective-C over the years, but coming back to it from proper modern languages like Java, C# and Ruby is just painful. It's really showing it's age and I harbour a hope that the macruby work Apple's doing right now is actually going to become the official way to write Mac and even iPhone software over the coming couple of years. That would be just perfect as the underlying Objective-C stuff would still be there for compatibility's sake and performance where necessary. Go on Apple, you know you want to!

Anyway, that mini-rant was not what I came here for. I've been wrestling with the best way to name and use instance variables. Version 1 was to name them in no special way at all, but then you end up with confusion between properties and the underlying variable and also with methods that want to use a parameter with the same sensible name (as is often the case with init methods):

@interface Person : NSObject
{
    NSString *name;
}
@property(nonatomic, retain) NSString *name;
@end

@implementation Person
@synthesize name;
// This gives a compiler warning because parameter name masks the instance var.
// Calling the parameter anything else is ridiculous though.
– (id)initWithName:(NSString *)name
{
    …
    // Need to remember to use self.name rather than name if we want to use the property.
    // It's easy to accidentally just assign directly to name and get a messed up retain count.
    self.name = name;
    ….
}
@end

So I've decided it's probably superior to use a prefix for the instance var itself, and though I'd always used m in the past, I'm going for _ here because it seems to be an Objective-C convention:

@interface Person : NSObject
{
    NSString *_name;
}
@property(nonatomic, retain) NSString *name;
@end

@implementation Person
// Note that we have to use some extra syntax here to hook up the non-underscored property.
@synthesize name = _name;
// Now the param doesn't clash with anything.
– (id)initWithName:(NSString *)name
{
    …
    // Property works exactly as before, but direct assignment with _name = name really
    // stands out so we're only likely to do it knowingly.
    self.name = name;
}
@end

Finally I end up agonising over whether I should always access my instance variables via a property (self.whatever), or whether I'm OK to use them directly (_whatever). Some purists argue that it's worth encapsulating with a property and always using that property. This way you can change your underlying data types but potentially retain the same property methods without breaking the code that uses them – i.e. it's an extra layer of abstraction that protects you from breaking changes. A few years ago I might have bought that, but these days I only add in layers of abstraction when they're truly needed, so I will use the property for external access and the instance var directly for internal access (though I'll always assign to the property to ensure retain counts are correct). I can easily refactor to add in the abstraction if necessary at a later point, but if I don't need it now then I won't bother with it.
Mac OS X comes with a lot of fantastic stuff built-in, like Java, Ruby, Python etc. The downside to this is that users tend to stick with the stock installs of those items and never upgrade them, which can leave them a long way behind the curve. I just ran into that problem when trying to install the latest version of Ramaze (my favourite Ruby web application framework) from the official gems. The IRC channel #ramaze was useful as always and provided the solution. The problem is that rubygems on OSX 10.5 is old and tired, but you can tell it to install a very specific version of innate that sorts it out. So from scratch, assuming Mac OS X 10.5 with the stock Ruby 1.8.6 install:
> sudo gem install innate -v 2009.04
> sudo gem install ramaze

Obviously as new versions of innate and ramaze come out, the exact version of innate required will change. You can tell which verison you need by trying the ramaze install and looking at the error message.

Update: Actually now Ramaze and Innate 2009.05 have been released, it seems things work just fine without any special incantations. So you can just sudo gem install ramaze and you're away.
Many people don't know about Apache Bench, even though it may be installed on their system. For instance it's installed on Mac OS X by default. It's a very simple command line utility to perform basic stress/performance testing of websites. It can request a given URL repeatedly, then report back statistics. I generally use it in this form:

> ab -n 100 -c 4 http://www.somewebsite.com/test/page.htm

Dissecting that command:
  • ab is the Apache Bench executable itself (found in /usr/sbin on my machine)
  • -n 100 tells it to send the request 100 times 
  • -c 4 tells it to use 4 concurrent threads to do so
  • finally we have the URL itself. 

Even though it's simple, there are some important gotchas worth knowing about:

  • Remember to put the URL in single quotes if it contains characters that would otherwise be interpreted by the shell. This is often the case for any URL with a query string, as the & characters will mess things up otherwise. 
  • If using a base URL for a site (just host name), you must use a trailing slash. http://foo.com doesn't work, but http://foo.com/ does work. 
  • Quite often you may see in the statistics "Failed requests: 5" or similar, followed by a list of the types of failure: "(Connect: 0, Receive: 0, Length: 5, Exceptions: 0)". If the only type of failure that actually occurred is 'Length' then don't be alarmed. This simply means that each request (for the same URL) returned a different length response, which ab regards as suspicious. However it's perfectly normal for dynamic webpages, especially if they include the time or other very dynamic data on the page. 
  • I find on one of my machines that it just doesn't like localhost as a hostname, so I have to use 127.0.0.1 instead. I have no idea why, as localhost works fine in other contexts on the same machine. 
07. April 2009 · 2 comments · Categories: Mac
I've seen quite a number of MobileMe sync problems over the last couple of months. Some items that I add/delete/modify in my calendar don't make the jump between laptop and desktop, or vice versa. It's completely intermittent and always works perfectly if I deliberately try to catch it out. This is extremely unhelpful of it, as it means I just can't trust my calendar on either machine to be correct.

Picture 7 
I've found a way to at least get things back in sync (as far as I can tell without doing an exhaustive comparison) though it remains to be seen whether it will actually stop things going wrong again. On all machines, open the iSync application, open its Preferences, then click the "Reset sync history…" button, and select "Merge" when asked. It might ask several times, for various types of sync data, with big spinny-arrow pauses in-between. You're putting yourself in the hands of MobileMe's sync algorithms here, so don't come crying to me if it makes your kettle fur up with scale and your cat leave home. I'll update this post as and when I determine if the more general problem is licked. Sadly my gut feeling is that it's too much to hope.

Update: Still been having problems and have been tearing my hair out. The recent OS X 10.5.7 update promises some sync improvements though isn't specific about what. I'm hopeful, but I won't know for a couple of months as it usually picks just one or two important items to not sync every now and then. Enough to keep me on my toes.

Rather mysteriously, my bluetooth mouse suddenly stopped responding with no warning. I assumed it was duff batteries, though I'd normally get a warning a good while before they conk out completely. Changed them, but still no dice. I attached a wired mouse and did some digging – basically Bluetooth no longer seemed to exist on my Mac! The menubar widget claimed bluetooth was 'not available' and the System Preferences Panel said similar. Restarting didn't help – in fact it made the menubar widget and System Preferences Panel disappear entirely!

After a bit of digging on the web, what worked for me was to reset PRAM. Shutdown computer, then start it up whilst holding down cmd-option-P-R until it chimes a second time. Actually I held down until a third chime for good luck. Seems to have done the trick!

Update: It then failed again shortly afterwards. Next move was to delete a critical prefs file. Best not to do this unless you have a clue what it means:
  • sudo mv /var/root/Library/Preferences/blued.plist ~/Desktop/

At the same time I shutdown the computer, removed all attached cables, opened it up and pressed the PMU/SMC reset button down near the RAM (this is a PowerMac G5 tower) then restarted. It seems to be OK for now. It did mean the clock resetting to 1970 and me having to wait for all my iCal notifications to stream in once I'd reset to 2009.

Update 2: And it's gone again. Maybe it'll never be back. I swear if Apple sold some sort of mid-tower machine – somewhere between an iMac (but without a screen) and the Mac Pro, I'd buy one without a second's hesitation. I've been waiting for years for this machine, on the assumption that it's an obvious hole in their line-up and will be along any moment, but I've been hideously disappointed.

Update 3: It seems that if I shutdown the computer rather than simply restarting, my bluetooth comes back to life. At the moment it's been fine for all of today, but it might flake out on me at a moment's notice for all I know.

Update 4: Correction – resetting PRAM by holding down cmd-opt-P-R until you hear a second chime is vital. Simply shutting down and restarting does not seem to do it. At the moment I sometimes get a few days of successful use between failures.

I've been experimenting with Ruby 1.9.1 and trying to make it my natural home recently. Crucial to that was getting the mysql gem installed. Actually it's fairly straightforward with the 2.8.1 version of the gem and only very minor mods to the official instructions at http://www.tmtm.org/en/mysql/ruby/ were required.

Note that I have only tried this to work against MySQL 5.0.x, which I have installed in /usr/local/mysql, as all my previous attempts to use MySQL 5.1 have failed miserably and I've given up on that for now. These instructions install from source, resulting in a fresh /usr/local/ruby191/lib/ruby/site_ruby/1.9.1/mysql.bundle. Then you can simply require 'mysql' in your Ruby code and you're away.

  • Downloaded 2.8.1 source tgz from RubyForge, linked from http://www.tmtm.org/en/mysql/ruby/ downloads section.
  • Expanded the tgz with Finder, then opened a command prompt…
  • > cd mysql-ruby-2.8.1
  • > ruby extconf.rb –with-mysql-config=/usr/local/mysql/bin/mysql_config -with-mysql-dir=/usr/local/mysql
  • > make
  • > sudo make install
Et voila! Note that make did output a bunch of warnings about implicit 64/32 bit conversion that suggests the code isn't entirely 64 bit happy, but I've not observed any problems as a result. Yet.

I've been following the progress of MacRuby for a few months now and was looking forward to the next release. Finally, and a month or three after it was expected, MacRuby 0.4 is here, according to the MacRuby blog.

MacRuby is, to keep it simple, an implementation of Ruby 1.9 built in Objective-C with transparent calling between the ruby and Obj-C worlds. For instance Ruby Strings are actually NSStrings in MacRuby and have all the powers of both. This along with some other neat integrations provided by the team allow you to write Mac OS X Cocoa apps using Ruby instead of Obj-C, or even a combination of both. If like me you think that Obj-C is a dinosaur that doesn't deserve a place in the modern programming world, this is great news. There seems to be a lot of momentum behind this project and I wonder if it may eventually become quite a fully fledged citizen for Mac app programmers – maybe even ultimately taking over from Obj-C for most Mac OS X development. I can but hope.

One of the many neat improvements in 0.4 is the ability to bundle the MacRuby runtime into the app itself so the user need be none the wiser, and certainly doesn't need to install MacRuby.