Archive for the ‘Mac’ Category
No more busywork! DRY up your NSString constants
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.
Lightweight inline formatting for NSAttributedString
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
Using vDSP_deq22 as a bandpass filter
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 |
Fixing Bluetooth sleep issues with MacBook and Magic Trackpad
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).
MySQL gem for Ruby 1.9.x on Snow Leopard or Lion (Mac OS X 10.6 or 10.7)
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.
as_kmldoc: easily visualise PostGIS queries as KML in Google Earth
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
.
Tab completion for Stata variables in TextMate
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.
O2 mobile broadband on a Mac: tips for you, suggestion for O2
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.
Growling Mac backups with rsync
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.
Free Adobe fonts
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.