George MacKerron: code blog

GIS, software development, and other snippets

Archive for the ‘Mac’ Category

No more busywork! DRY up your NSString constants

without comments

Preamble

In the last few years, Objective-C has become enormously DRYer. For example: in the past, adding a property to a class meant adding several of: an ivar, a @property, a @synthesize, a getter/setter, and a release call in dealloc. Worse, renaming or deleting the property meant updating all these. This was error-prone busywork, and made iOS development frankly pretty tedious.

Nowadays a single @property is often all that’s needed. Plus of course we’ve lost all that retain / release / autorelease noise, and got fast enumeration, literals for NSNumber, NSArray, NSDictionary and so on. This is great (and is one reason why I’ve come back to Xcode after a brief dalliance with RubyMotion).

Anyway, I really do hate repeating myself, and one of the more annoying remaining areas where this has been necessary has been string constants. These are pretty widely used in Cocoa for NSNotification names, dictionary keys, and so on.

Problem

In the past I’ve used #define in my headers. For example,

#define TapNotification @"TapNotification"

This seems like fairly innocuous repetition, but it’s still annoying. And the idiomatic/Apple way is worse. You do this in the header file:

extern NSString* const TapNotification;

Backed up by this in the implementation file:

NSString* const TapNotification = @"TapNotification";

We type the same identifier (and its accompanying line noise) no fewer than THREE times.

Solution

The best solution I’ve found involves a macro plus a one-line sed command.

The macro goes like this:

#define StrConst(s) extern NSString* const s;

And the one-line sed command (added as a build phase straight after ‘Target Dependencies’) goes like this:

sed -nE 's/[[:<:]]StrConst[[:space:]]*\([[:space:]]*([^)[:space:]]+)[[:space:]]*\)/NSString* const \1 = @"\1";/pg' ${SOURCE_ROOT}/${PROJECT_NAME}/*.h > ${SOURCE_ROOT}/${PROJECT_NAME}/AutoStrConsts.m

Now all you do for a string constant is type this in your header file:

StrConst(TapNotification)

The macro converts this to the right form for the header, and the sed command searches all your headers to create a single implementation file that contains all the corresponding definitions (you’ll need to manually add this file to the project when it’s first created).

If you think this is too much magic, I’ll understand. But for me, it’s a necessary battle in the war on busywork.

Written by George

July 2nd, 2014 at 10:13 am

Posted in iPhone,Mac

Lightweight inline formatting for NSAttributedString

without comments

For Cocoa developers: I’ve just put a small category on NSMutableAttributedString on Github.

It applies *bold*, /italic/, _underline_, -strikethrough-, ^superscript^ and ~subscript~ styles, and handles */nested/* and *overlapping /styles* properly/.

More details at https://github.com/jawj/NSMutableAttributedString-InlineStyles

Written by George

March 11th, 2014 at 4:13 pm

Posted in iPhone,Mac

Using vDSP_deq22 as a bandpass filter

with one comment

For reasons that may become clearer in future, I needed to use a bandpass filter in an iOS app. The DSP part of Apple’s Accelerate framework makes this lightning fast both for the programmer to implement and for the machine to execute … if the programmer knows how use vDSP_deq22, which is documented, at best, concisely.

The following functions produce the five-coefficient filter definition you need to pass to vDSP_deq22. Since this took me a little while to put together, I thought I’d share.

void makeBandpassFilterWithFcAndQ(float* filter, double Fs, double Fc, double Q) {
 
  // Fs = sampling rate, Fc = centre freq
  // with thanks to http://www.earlevel.com/main/2013/10/13/biquad-calculator-v2/
  // and https://github.com/bartolsthoorn/NVDSP
 
  double K = tan(M_PI * Fc / Fs);
  double norm = 1.0 / (1.0 + K / Q + K * K);
  filter[0] = (float)(K / Q * norm);
  filter[1] = 0.0f;
  filter[2] = -filter[0];
  filter[3] = (float)(2.0 * (K * K - 1.0) * norm);
  filter[4] = (float)((1.0 - K / Q + K * K) * norm);
}
 
void makeBandpassFilterWithFreqRange(float* filter, double Fs, double Fbtm, double Ftop) {
 
  // with thanks to 
  // http://stackoverflow.com/questions/15627013/how-do-i-configure-a-bandpass-filter
  // -- this sets Q such that there's -3dB gain (= 50% power loss) at Fbtm and Ftop
 
  double Fc = sqrt(Fbtm * Ftop);
  double Q = Fc / (Ftop - Fbtm);
  makeBandpassFilterWithFcAndQ(filter, Fs, Fc, Q);
}

And you use it like so:

float filter[5];
makeBandpassFilterWithFreqRange(filter, sampleRate, filterLoRate, filterHiRate);
vDSP_deq22(rawFloats, rawStride, filter, filteredFloats, filteredStride, numRawFloats - 2); 
  // rawFloats and filteredFloats are pointers, of course

Written by George

February 4th, 2014 at 2:37 pm

Posted in iPhone,Mac

Fixing Bluetooth sleep issues with MacBook and Magic Trackpad

without comments

We have an old MacBook (the original white Intel model from 2006) running EyeTV as our telly.

Apple’s Magic Trackpad makes a handy remote control for this setup. Unfortunately, Bluetooth on the old MacBook is highly temperamental. Built-in Bluetooth regularly fails: out of the blue, the Mac decides that it has no Bluetooth module after all, puts a wavy line through the menu bar icon, and ignores the trackpad. The only fix for this is to shut the computer down, and leave it off for several minutes. This is annoying.

I had an old D-Link Bluetooth dongle (DBT-120), so I tried using this instead. This is better, in that the failure mode is less annoying. Using the dongle, the trackpad’s Bluetooth connection only fails after a prolonged sleep. It looks as if it’s still connected, with a dotted line across the Bluetooth icon, but it’s unresponsive. This can be fixed by simply unplugging and replugging the dongle. But that’s still a pain, and is rather a compromise of the ‘remote’ in remote control.

It turns out that the post-sleep unresponsiveness may also be fixed by restarting the Bluetooth daemon, by typing sudo killall blued in the Terminal.

This is good news, because we can automate this action using sleepwatcher.

If typing sudo killall blued in Terminal solves your Bluetooth issues after sleep, then you may want to use sleepwatcher too. (Note that after a sudo command, you may be asked for a password. Nothing will show up as you type, but that’s OK: just type your password and press Return).

Read the rest of this entry »

Written by George

October 11th, 2012 at 1:55 pm

Posted in Mac

MySQL gem for Ruby 1.9.x on Snow Leopard or Lion (Mac OS X 10.6 or 10.7)

with one comment

Updated May 2012 for Lion

The secret to getting the MySQL gem to install and function with Ruby 1.9.x on Snow Leopard or Lion is:

  • Install MySQL using the 64-bit .DMG package installer from dev.mysql.com
  • Install Ruby using RVM or (preferably) rbenv
  • Add these to lines to ~/.bash_login or ~/.bashrc or ~/.profile as appropriate:
export PATH="/usr/local/mysql/bin:$PATH"
export DYLD_LIBRARY_PATH="/usr/local/mysql/lib:$DYLD_LIBRARY_PATH"
  • In a new shell (Terminal window), type gem install mysql as normal.

I’m posting this mainly as a record for myself, having wasted a lot of time in the past trying strange incantations from comments on various other blogs posts.

Written by George

August 4th, 2011 at 3:47 pm

Posted in Mac,Ruby,SQL,System admin

as_kmldoc: easily visualise PostGIS queries as KML in Google Earth

with one comment

PostGIS has an st_askml function. This turns geometries into fragments of KML, and thus takes you most of the way to easy visualisation of spatial queries using Google Earth. But not all the way: these fragments have then to be assembled into a complete document.

I’ve written some wrapper and aggregate functions to automate this. They’re probably deeply inefficient — I wouldn’t advocate building your next web service on them — but for one-off eyeballing of query results I find them really useful.

The key functions are called as_kmldoc; you could see them as the missing aggregate versions of st_askml.

Read the rest of this entry »

Written by George

September 29th, 2010 at 2:58 pm

Posted in GIS,Mac,PostGIS,SQL

Tab completion for Stata variables in TextMate

with 4 comments

I recently switched to TextMate for editing Stata .do files: unlike Stata’s built-in editor on the Mac, it has syntax highlighting and other goodies via Timothy Beatty’s bundle (now hosted by Dan Byler).

One thing it doesn’t have, though, is tab completion. Or rather, it didn’t, until now.

Read the rest of this entry »

Written by George

February 6th, 2010 at 5:59 pm

Posted in Mac,Stata

O2 mobile broadband on a Mac: tips for you, suggestion for O2

with 21 comments

Until Monday, O2 is offering a half-price USB dongle for pay-as-you-go mobile broadband. Buy it via Quidco, and you get not only the dongle but also a month’s access (or 3GB, whichever is the sooner) absolutely free.

So: free modem. No further commitment. And the opportunity to buy access a day at a time for £2, on a train journey, for example, or in an airport lounge, where the cheapest paid-for WiFi option is rarely less than £5, and often nearer £10. Handy.

Update. O2 is no longer doing the modem at half price, but the Quidco cashback has increased so that it still fully covers the modem and a £15 top-up.

Read the rest of this entry »

Written by George

August 1st, 2009 at 1:52 pm

Posted in iPhone,Mac

Growling Mac backups with rsync

with one comment

Between Time Machine and services like Dropbox, paranoid levels of backup are surprisingly painless to achieve on the Mac these days.

Still, just one more copy of your data, in just one more continent, surely can’t do any harm, right? One that won’t burn down with your house, but also isn’t just wafting vaguely in the Cloud at someone else’s whim. One that elevates your backup system from sensibly paranoid to borderline OCD. One, in this case, brought to you by rsync, find and Growl.

Read the rest of this entry »

Written by George

August 1st, 2009 at 12:40 pm

Posted in Mac,System admin

Free Adobe fonts

without comments

Quick tip: you can get hold of some of Adobe’s very nice professional fonts for free when you download the InDesign CS4 trial (and possibly other CS4 apps too).

These include:

  • Caslon Pro
  • Chaparral Pro
  • Garamond Pro
  • Minion Pro
  • Myriad Pro

If you don’t want to actually install InDesign, you can get to the fonts like so (if you’re a Mac user):

  • Mount (double-click) the downloaded disk image
  • Mount another disk image found on the newly mounted disk, at Adobe InDesign CS4/payloads/AdobeFontsAll/AdobeFontsAll.dmg
  • The fonts are inside /Assets/contents on this second disk

Note that these fonts may well be covered by a very restrictive licence: I haven’t checked.

Written by George

May 28th, 2009 at 1:17 pm

Posted in Mac,Web design