Another Octopress Blog

September 9, 2012

I made the transition from WordPress to Octopress. I’d been a WordPress user since sometime in 2003, when I started my 1128 blog. WordPress was incredible: the installation was remarkably painless and the features (admin interface, layouts, etc.) were top notch as well. Over the years WordPress has improved quite a bit, too. But WordPress has also grown somewhat notorious for performance issues (under heavy load, anyway), and there were occasional security problems as well.

Perhaps due to these challenges, static site generators like Octopress are becoming more popular. The advantage is that the code runs on your local machine and generates a bunch of HTML files. Then you upload (rsync, in my case) them. This makes your site faster – it doesn’t have to converse with a database server to get the posts – and a lot more secure. There’s no PHP script running on the server with bugs waiting to be compromised. The hosting account itself is still hackable, of course, but there’s only so much we can do about that.

So when my friend Robert emailed a couple months ago to let me know that my blog had some link spam in the footer (coded so that it didn’t when I visited the site), I decided it was time to say goodbye to WordPress. I blog rarely enough that it needs to be frictionless, and though it was interesting to track down where the spam was being injected, I doubted it would be as interesting in future occurrences. It was time to get serious about Octopress.

As an aside, I did spent some time trying out Hyde, because Python is higher on my list of preferred languages than Ruby (important if I ever wanted to tinker with the code) but Hyde is not (yet?) as much of an off-the-shelf blogging platform as Octopress is. Octopress won.

For the most part the switch was easy; I used Matt Gemmell’s post as a reference. Initially there were no comments, as it is A) fashionable these days and B) it’s a static site. However, this weekend I opted to setup Disqus, which is akin to off-shoring your comments.

I do miss WordPress to a certain degree. It was much easier to sign into the admin interface and compose a new post, write a little, and decide to save it as a draft (and forget about it). With Octopress it’s a more manual process.

  • rake new_post['Some Title']
  • Fire up TextMate 2 and open the .markdown file.
  • Write.
  • Don’t finish post for various reasons. Go to the Octopress docs to remind myself how to set a post as a draft (note to my future self: published: false).
  • rake preview / rake generate / rake deploy

The downside of this is that if you never finish a post (or decide not to post it) and never set it to be a draft, when you come around later and actually post something you could easily inadvertently post your not-intended-for-publication post. So some care is required. For now I’ve modified the Rakefile to include the published: false line in the new_post template.

You served well, WordPress, and you will be missed. My thanks to the many developers who made WordPress great.

Comments

Launch at Login Implementors Support Group

September 6, 2012

I’ve had a number of improvements in the pipeline for SwiftText 1.1.0 for quite some time, and finally submitted it to the Mac App Store tonight. One of the most difficult features to get right was Launch at Login. This was a feature that was in 1.0 and was fairly easy to implement at the time. However, in this brave new world of sandboxed apps, launch at login is a bit of a beast. If you’re thinking about adding it to your application, or perhaps you’re struggling to make it work, perhaps this post will help.

Sandboxed apps need to use a helper tool to do the actual launching for them. In short, the helper app is bundled under Contents/Library/LoginItems and its bundle identifier is passed to SMLoginItemSetEnabled(). delite studio has a very helpful post on this, but you’ll want to make sure to read Mike Cohen’s own post containing some key corrections. Your helper app will need to do some path acrobatics to concoct the path to your main application, which it launches with -[NSWorkspace launchApplication:], and then calls [NSApp terminate:nil].

If you follow the above, you should have a working launch at login feature. There was one more hurdle for me to overcome, however. My application passed the Validate step within Xcode, but when I uploaded the binary I was told my application had an “Invalid binary”:

Invalid Provisioning Profile Location - The provisioning profile for your Mac OS X app must be located in the Contents directory of the main app bundle. A provisioning profile is optional, but you cannot submit more than one.

What the iTunes Connect robot was trying to tell me was that my helper tool was, evidently, incorrectly signed. Using this Stack Overflow answer I was able to re-sign it in a Run Script build phase, which passed the robot’s muster. (One note about that answer: I found that copy-pasting the lines from the answer yielded a non-working script. By retyping the paths I was able to get it working. Bad characters in the mix, I presume.)

Why so much work to get such a simple feature working? The launch-at-login APIs were never developer-friendly: the old Launch Services method was a couple dozen lines, all told. Here we have less code, but many more obstacles to maneuver. Why the helper application, though? As far as I can tell the SMLoginItemSetEnabled() call (part of the Service Management Framwork) is not really intended for matters so trivial as launch at login. I suspect that it was simply the last man standing after the Launch Services method was knocked out by sandboxing. From a developer’s perspective this is a pretty unpleasant pattern. I see three possible explanations:

  • Apple didn’t have time to concoct a new sandbox-friendly API for this in time for 10.7/10.8.
  • Apple doesn’t see it as unpleasant, or not unpleasant enough.
  • My expectations are too high.

My money’s on the first. With the Service Management method, the user must use the application itself to toggle launch at login. Applications with this enabled don’t show up in the Users & Groups Login Items pane, nor do they show a checkbox in the ctrl-click menu on the dock. Not the best user experience. Perhaps there will be a better solution in 10.9. Now to write a bug in hopes that it will help that happen. Here’s what I’m thinking:

@interface NSApplication (LaunchAtLogin)
@property BOOL launchAtLogin;
@end
Comments
Tags: ,

MTRandom: An Objective-C Random Number Generator

September 3, 2012

Most of the time when we need a random number, we use srandom() & random(), or perhaps arc4random(). In the old days we might have used srand() and rand(), until somebody told us that random() was better.

Sometimes we want a sequence of random numbers to be reproducible. Say we’re writing our own Minecraft and we want users to be able to share seeds for the landscapes they find. The above functions work fine for that, as long as we’re the only one using them. Unfortunately they’re not thread safe (see my test code to confirm). They manage a single state behind the scenes, so if we wanted to run, say, two landscape generation routines in parallel, we’d be out of luck.

That’s where MTRandom comes in. MTRandom is an Objective-C wrapper for Mersenne Twister, a pseudo-random number generator.

MTRandom *random = [[MTRandom alloc] initWithSeed:5];
uint32_t r = [random randomUInt32From:5 to:10];   // [5, 10]
double   s = [random randomDouble];               // [0.0, 1.0]
double   u = [random randomDoubleFrom:0 to:M_PI]; // [0, 3.14159...]

There are a few more examples in the README.markdown.

It also conforms to NSCoding and NSCopying, so you can archive it with game state, or make copies when searching a game tree. The repository includes a set of basic unit tests, and best of all it’s BSD licensed (even Mersenne Twister). It’s available on GitHub: github.com/preble/MTRandom.

Comments

Xcode Snippets

July 25, 2012

Xcode’s snippets feature is rather handy. It’s what drives many of the autocomplete templates. For instance, if you type init on a new line and hit return, Xcode will create a template for an -init method.

Until recently I haven’t bothered to create my own snippets, which can be done in three easy steps:

  • Selecting a block of text you wish to make a snippet.
  • Drag it onto the Code Snippet Library, which is part of the Utility Area (lower right hand side).
  • Customize by entering the Completion Shortcut, or wrapping tokens in <#token#> so that you can tab between them after the snippet has been inserted.

I do a fair amount of Quartz development, so today I created a a snippet which has already proven useful. I’ve set its completion shortcut to cgbitmapcontextcreate:

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef ctx = CGBitmapContextCreate(<#data#>, <#width#>, <#height#>,
	                                     8, <#width#> * 4, colorSpace, 
	                                     kCGImageAlphaPremultipliedLast);
CGColorSpaceRelease(colorSpace);

I’ve made a separate one just for color spaces, cgcolorspace, as for some reason the repetitiveness of creating and releasing RGB CGColorSpaceRefs has lost its luster.

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
<#code#>
CGColorSpaceRelease(colorSpace);

Thankfully you can stomp all over the symbol names that will be otherwise provided by autocomplete, so when I’m about to create yet another CGColorSpaceRef, perhaps forgetting my snippet, Xcode will show me the snippet as the first autocomplete option in addition to the usual bunch.

A pleasant side effect of this is that you can fix some of Xcode’s annoying autocompletes, due to how snippets take priority over other autocomplete suggestions. For instance, when I type NSStri in Xcode, the default autocompletion is NSStrikethroughStyleAttributeName. Probably not what I wanted. I can use snippets to fix this by creating an NSString snippet with the very same completion shortcut, and voila, autocomplete gives me just what I want when I next start typing NSString.

Comments
Tags: ,

Briefly on Sparrow et al.

July 21, 2012

Beautifully designed 3rd party apps are part of what makes the Mac platform such a great platform. We can be fairly emotional about our beloved Mac ecosystem. So it’s natural to feel injured when we learn that one such app has suddenly become encased in ice. Matt Gemmell is right, however, when he says:

People try to dress their reaction up as a principled stance or a community cause, but that’s at best wrong-headed thinking, and at worst wilfully egocentric bullshit.

Don’t worry; he’s not going to sugar-coat it any more than that.

Comments