Swift’s String.write(toFile:…) can’t handle tildes

let path = "~/Desktop/sigh.txt"
try "WTF?".write(toFile: path, atomically: true, encoding: .utf8)

Result?  Explode:

Error Domain=NSCocoaErrorDomain Code=4 "The folder “sigh.txt” doesn’t exist." UserInfo={NSFilePath=~/Desktop/sigh.txt, NSUserStringVariant=Folder, NSUnderlyingError=0x1018110b0 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}

And since there’s no documentation on that write() method, and this is obviously a perfectly reasonable request that can’t sanely yield that bizarre error message, you could be forgiven for having no idea how to fix this.

Long story short, in macOS Sierra at least that write() method happens to be implemented as NSString’s writeToFile:atomically:encoding:error: method.  If you look at the documentation for that method, it states:

path:  The file to which to write the receiver.  If path contains a tilde (~) character, you must expand it with stringByExpandingTildeInPath before invoking this method.

WTF it can’t actually say that in the Swift method’s documentation (or indeed why it has none at all), or why the exception thrown can’t at least give the real reason, or of course WTF it can’t just do the right thing and handle tildes in the path…  I have no idea.  This smells like a combination of laziness, snafu, and poor judgement in carrying over bad behaviours and design flaws from Objective-C.

So instead you have to do:

try "WTF?".write(toFile: (path as NSString).expandingTildeInPath, atomically: true, encoding: .utf8)


Nikon SnapBridge


Nikon have released the SnapBridge app so that the much-touted Bluetooth+Wifi capability of the D500 can actually be used.  A mere eight months after it was announced.  Fuck you too Nikon.

However, as I’d clearly forgotten, it’s not very useful anyway.  It doesn’t work with raws, you see.  Doesn’t even acknowledge that they’re in the camera, on the card.  It took me twenty minutes of screwing around with the app, wondering why it was so completely broken and dysfunctional, before I stumbled upon a tech support article for it buried half a dozen layers deep inside Nikon’s website (yes, there’s essentially no documentation within the app itself).

It does appear to at least work for geotagging & time sync, which is something.  Something Nikon could have put in natively for a $1 GPS receiver, and then not have to kill my iPhone battery to accomplish rudimentary tasks.

The almost saving grace of the D500 is its speed – specifically the UHS-II support, which helps it clear out its buffer extra snappy, given a decent SD card.  That means I can turn on NEF+JPEG without much concern about slowing down burst shooting, and only marginal concern about the wasted SD card space.

But it’s only almost saved by it.

The problem, you see, is that even if you abuse the NEF+JPEG option to yield little JPEG turds on your SD card – and even though those JPEGs can be surprisingly decent quality, even on ‘Small’ and ‘Basic’ settings – in NEF+JPEG mode the camera insists on using the JPEG version for all in-camera playback.  It becomes completely impossible to view the actual NEF.

Now, granted when ‘viewing’ NEFs in-camera you’re only getting the JPEG preview that’s built into them anyway, but still – it’s at least a decent quality, full-size preview.  You can at least zoom all the way in.  Not so if your JPEG turds are not full-size.

Which might be a good enough option, if one is willing to waste up to 50% of your space saving full-size JPEGs alongside the NEFs.

But, SnapBridge transfers the images via Bluetooth only.  Even when you’ve configured it to bring over the originals, at up to 10 MB each.  It can take minutes to transfer a single image of that size at Bluetooth speeds – I know, I accidentally proved it empirically.

Now, you can limit the transfer to 2 MP versions of those JPEGs, but 2 MP is tiny, even by Shitagram standards.  The ‘Small’ JPEGs the D500 saves natively are 5.2 MP, for point of reference.

So the 2 MP transfer option – call it “Thumbnails only” – is not a practical or useful option.

So we’re back to having to use full-size JPEGs, alongside the real photos (the NEFs).

And remember the prior point about abysmal Bluetooth transfer speeds?  To make SnapBridge’s auto image transfer plausible to use with any frequency – let-alone leave on permanently – you need tiny file sizes.  Even on the highest compression setting (vanilla ‘Basic’) the 21 MP JPEGs are several megabytes.  Only by using the ‘Small’ image size – which is frankly still good enough for Instagram types – can you get the sizes into the sub-MB range, and transfer times down to ‘merely’ a few seconds per photo.

So you’re stuck between a rock and a hard place.  The net result is that the whole image download thing’s kinda horrible and useless to me.  Which makes me sad, because it could easily have been implemented much better.

The CamRanger remains a significantly better experience in almost every respect – the main detractor being the additional monetary cost it imposes.