Matthew Palmer Top Articles Vanilla Rocket

    Top Articles in 2017

  1. 2016 Macbook Pro Battery Pack – Anker PowerCore 20100

    While travelling around Australia and the US, I needed a good way to give my Touch Bar MacBook Pro and iPhone 5 a bit of extra charge.
  2. Vanilla: Hide menu bar icons on your Mac for free

    I released Vanilla, an app that hides Mac menu bar icons, and wrote this behind-the-scenes article about its development and launch.
  3. How to Add a Launch Image for the iPhone 6 (Plus)

    A quick guide on how to add a launch image in Xcode for the iPhone 6, 7, and 8.
  4. Example Code for Using Swift to Save and Query iOS Keychain

    The origin story for Locksmith, my iOS Keychain library with over 2,400 stars on Github.
  5. Remapping Keyboard Keys on Mac OS X Mavericks

    How to remap any of your keyboard keys to any combination of keys on Mac OS X Mavericks. I got hooked after remapping Caps Lock to Command+R.
  1. How to Install VirtualBox on macOS High Sierra

    I tried to install VirtualBox on macOS High Sierra, but I got an error about kernel drivers, system extensions, and kernel modules not being installed. The VirtualBox installer fails with “The installation failed” where it “encountered an error that caused the installation to fail.”

    Go to System Preferences > Security & Privacy. Click the ‘Allow’ button at the bottom. Re-run the installer. More detailed instructions are below.

    VirtualBox on macOS failed to install

    VirtualBox has an error when installing.

    • Run the VirtualBox installer just like any other installer.

    • You might see a prompt from macOS about not allowing unsecure system extensions. You can click ‘Next’ for now.

    • After reaching the end, installation will fail with the message above.

    • Navigate to System Preferences > Security & Privacy. At the bottom of the window, you should see a message saying “System software from developer, ‘Oracle, America, Inc.‘ was blocked from loading.”

    VirtualBox allow kernel modules

    • Click the lock in the bottom left corner, enter your password

    • Click ‘Allow’ next to the ”blocked from loading” message.

    • Re-run the VirtualBox installer. It should succeed.

    VirtualBox install success on High Sierra

    How to add a shared folder for Ubuntu on a macOS High Sierra Host?

    Side note: here’s how to share files between a Ubuntu virtual machine and macOS High Sierra on VirtualBox.

    • Download, set up your VM. See above.

    • Open settings for the VM. Click the “Shared Folders” tab. Add your folder and select Yes for “Auto-mount”

    • Run the VM

    • While the VM is running, in the Mac menu bar go to Devices > Optical Drives > Choose disk image…

    • Select the VirtualBox Guest Additions image, for me this is located at /Applications/VirtualBox.app/Contents/MacOS/VBoxGuestAdditions.iso. Once the Choose disk image… option was selected, you were probably shown a file picker. Press Command-Shift-G and then type in that file to choose the VBoxGuesAdditions.iso.

    • You might need to force mount/unmount. You’ll be prompted by VirtualBox if this is necessary.

    • Restart your VM.

    • Run the following command to install prerequisites for the Mac VirtualBox Guest Additions: sudo apt-get -y install gcc make linux-headers-$(uname -r)

    • Then run sudo /media/cdrom/VBoxLinuxAdditions.run to install the Guest Additions

    • Restart your VM again.

    • Run sudo usermod -g vboxsf USERNAME where USERNAME is your guest OS username. This will let your user access the shared folder.

    • Your folder will be at /media/sf_FOLDER_NAME, so cd /media/sf_FOLDER_NAME

  2. Volunteering at CTO Summit

    At CTO Summit, CTOs, VPs, and engineering managers shared the behind-the-scenes of their companies’ engineering teams with 150 attendees. They talked through surviving rapid-growth engineering and orchestrating teams at scale. They also needed volunteers to help run the conference, which is how I got in.

    When I graduated high school, I plainly looked forward to seeing what was outside the tiny Australian town I grew up in. The idea that a few years later I’d be in the Times Square Nasdaq building was, and is, ludicrous. That’s one of those places that exists in movies—I always felt there was like a 79% chance it was fictional.


    seriously

    Seriously, it’s this place.


    Turns out it’s real, and you need a lanyard and a nametag to be there. That’s where I come in: for the morning, I had to greet and register some of the most influential people in tech. Cool.

    My mate at registration was a Ghanian expat with an undergraduate in geospatial systems. As you’d expect, our chit-chat turned into a diagram-and-equation complete overview of GPS (between attendees’ arrival, of course). I laughed at the lengths the government have to go to secure GPS signals from timestamp tampering, which would totally ruin your phone’s positioning system.


    For the afternoon, I was on speaker tech support. In the 30 seconds between lightning talks, I ducked up on stage, reconfigured the display, changed to the next presentation, and fiddled with the clicker, hopefully without the audience noticing. And if anything went wrong, just like… fix it. The reward? Front row for every talk that afternoon.

    Two outstanding talks from the nine I was lucky to see: Randy Shoup and Edith Harbaugh.

    Randy (Stitch Fix, eBay, Google) talked about the practical technical concerns of microservices at Stitch Fix. Watch the video of the talk when it comes out—it’ll be great. Two high level notes: don’t do microservices if you’re small, and this gem: if you don’t have big technical problems while growing, you over-engineered and cost the company early. Embrace that mistakes are inevitable—just make sure your mindset is open to tackling them.

    I had looked forward to Edith Harbaugh’s talk all day since I love LaunchDarkly (seriously, read this article on Building vs. Buying and tell me you don’t love a company that writes so cogently). Her talk, Software & The Art of Bicycle of Maintenance, told the story of her bike trip across North America, and shared the many insights she had. The most important thing? Take care of yourself. It’ll add water to your reservoir to use on the real fires.

    I learned from every talk that afternoon, and picked up so much from chatting to everyone in the hallways in the breaks. I’m grateful to Peter, Samantha, and Jon for having me on as a volunteer. I’ve volunteered at camps, festivals, and conferences now, and every single one has been really rewarding.

    If you’re interested in volunteering at something, do it.

  3. Emoji Bullet List ⚡ Behind the Scenes

    Have you ever seen tweets like these?

    Bulleted lists that use emoji

    • 🌟 look awesome
    • 💯 are perfect for sharing on social media
    • 😄 bring joy to boring lists

    (Can you guess how I made that emoji list?)

    Painful to write, though. Like, I know emoji better than most, and I struggle to quickly pick out the right emoji to go with each line.

    I built Emoji Bullet List to make creating emoji dot point lists really easy. Just copy in your list, hit the big “Emojify” button, quickly choose from the suggested emoji if the first suggestion doesn’t fit your needs, and hit “Copy” to get an emojified list back. Too easy!

    This idea originated as a nice-to-have feature for Rocket, but I realised I could use Rocket’s emoji keyword/phrase dataset to build this into a web app. More people can access it, it’s a bit easier to use, and hopefully a few more people will find Rocket because of it.

    I couldn’t figure out a good way to monetise it, so it’s completely free 🤷‍♂️.

    Technical Notes

    Simple, useful logging for Node.js apps

    I added unremarkable-yet-incredibly-useful logging with ten lines of JavaScript that lets me see in detail how (anonymised) users are interacting with the app. (This is great for low volume apps, but I don’t do this for services running at scale.)

    • Create a middleware function early in the chain that gives a user a random identifier as a cookie (using Express cookie-parser) when they access a page if they don’t have one already.
    app.use(cookieParser())
    
    app.use((req, res, next) => {
    	if (!req.cookies[COOKIE_NAME]) {
    		res.cookie(COOKIE_NAME, uuid(), { maxAge: 900000, httpOnly: true })
    	}
    	next();
    });
    
    • Create a second middleware function using the Express response-time middleware that logs the user’s cookie, what they’re requesting, and how long it took us
    app.use(responseTime((req, res, time) => { 
    	const cookie = req.cookies[COOKIE_NAME] || 'no-cookie                           '
    	console.log(cookie, req.path, time)
    }))
    

    (The extra spaces next to no-cookie are so that it lines up with our UUIDs in the logs.)

    • Since I use pm2 to manage the app in production, the log file gets handled automatically, and I can just pm2 logs to stream the app in use and see what people are doing in real time. This is pretty addictive. Let’s take a look at one example I saw.
    # A new user comes to the app, gets their identifier set as c5ff9a10
    0|index    | no-cookie  / 						0.5199119999999999
    0|index    | c5ff9a10   /styles.css 			0.39601899999999995
    0|index    | c5ff9a10   /app.js 				0.33612
    
    # Another new user comes in, set as 1378f9d0
    0|index    | no-cookie  / 						0.37545999999999996
    0|index    | 1378f9d0   /styles.css 			0.362075
    0|index    | 1378f9d0   /app.js 				0.491498
    
    # The first user asks for some suggestions and uses them!
    0|index    | c5ff9a10   /api/v1/suggestions 	0.964749
    0|index    | c5ff9a10   /api/v1/used-suggestion 0.5390269999999999
    
    # Some previous user comes back to the app and asks for a suggestion
    0|index    | f92af790   / 						0.46471999999999997
    0|index    | f92af790   /styles.css 			0.40573299999999995
    0|index    | f92af790   /app.js 				0.217364
    0|index    | f92af790   /favicon.ico 			0.31112999999999996
    0|index    | f92af790   /api/v1/suggestions 	0.921465
    
    # Our original user is playing around with different suggestions until they're happy
    0|index    | c5ff9a10   /api/v1/suggestions 	0.676022
    0|index    | c5ff9a10   /api/v1/suggestions 	0.8778859999999999
    0|index    | c5ff9a10   /api/v1/suggestions 	0.71288
    0|index    | c5ff9a10   /api/v1/used-suggestion 0.522269
    

    There are a bunch of fancier ways using external services or adding full user tracking, but honestly there’s nothing more fun than tailing your logs in realtime while someone is successful with your app.

    I even saw one person come in, play around with the app for a minute, and click on the link to my Twitter profile. I opened up Twitter, and 30 seconds later I had a tweet from them about how much they liked the app 😁.

    (As a side note, you’ll notice attackers and bots trying to crawl your site for security vulnerabilities. /manager/assets/modext/modx.jsgrps-min.js, /media/system/js/core.js, /privacy_policy.php (why!?), /a2billing/common/javascript/misc.js, are some common ones.)

    Dead-simple Node.js and Express app deployment on DigitalOcean

    I’ve got a dead simple deployment strategy that’s great for small apps. Put this in a file called node-simple-redeploy.sh (or whatever) in your project.

    #!/bin/sh
    
    # Copy this to your package. Change the IP.
    rsync -azv --exclude node_modules/ --progress -e ssh "$PWD" root@XXX.XXX.XXX.XXX:~/app/
    
    # You may need to npm install on the DigitalOcean box
    

    And to your package.json, add

    "scripts": {
    	...
    	"sync": "./node-simple-redeploy.sh",
    }
    

    And I simply npm run sync to update the app. Don’t do it at scale, but it’s super fast and works for small apps. I’m not fancy 🤷‍♂️.

    Other Notes

    • Like most web apps I make, it’s a one-page app using Node.js, Express, and MongoDB for long-term storage. On the frontend it’s pretty plain JS/jQuery/CSS. I love Flexbox more and more each day.
    • The emoji dataset is loaded into memory on the backend and we query from there, so it’s super fast.
    • I’m always surprised how simple implementing things like popup modals and selectable lists are in web development compared to iOS apps. It’s like 30 minutes of work to write your own.
    • Uses LetsEncrypt for HTTPS. So easy.

    If there’s anything you’d like me to write more about, let me know.

  4. 2016 Macbook Pro Battery Pack – Anker PowerCore 20100

    I’m travelling around for a while, and I’ve been on the hunt for a good way to give my 13-inch 2016 MacBook Pro (Touch Bar edition) a bit of extra charge. There’s information scattered around the internet on what works and what doesn’t, and I wanted to collect it here so that you don’t have to do as much research as I did.

    The short story: the Anker PowerCore+ 20100 with USB-C is the best way to charge a 2016 MacBook Pro using an external battery pack.

    Anker PowerCore pack for Macbook Pro

    The Anker PowerCore+ 20100 with USB-C. Source: Anker

    My Observations after Several Months of Use

    I’ve used the Anker for about four months now while travelling around the US. It’s survived camping trips to Washington and Yellowstone, domestic and international flights (N.B. it has to go in your carry-on), buses, trains, hostels in Nashville and hikes in Austin. Here’s what I’ve found:

    • It takes a long time to refill the battery on the Anker brick. At least overnight if you use the regular MacBook charger. The Anker USB-C Rapid Charger improves the charge time here if you need it (which you do).

    • The battery pack is pretty heavy. Feels about as heavy as the 13-inch Pro itself, although denser.

    • I can fit the pack in a pants pocket if I have to, but the thing is big and solid (and well-built!)

    • The “user interface” on the thing sucks. If you want to charge something, press the button on the front to make the lights come on. Then plug in your device. If you want to charge the brick itself, plug it in and maybe press the button. (I haven’t figured this out yet, after four months.)

    • The circle lights on the front will fill up. Eventually. Again, this thing charges slowly.

    • It holds about a MacBook Pro’s worth of battery charge when full. This is at least six full iPhone 5 charges (I actually ended up needing to charge my phone way more often than my laptop when I was travelling, so this was super handy)

    Overall, I highly recommend the Anker power brick. It’s reassuring to know you always have a power source when you need it. The Anker does the job it’s meant to, holds enough power, is well built, and has saved me more than a handful of times.

    Here’s the other stuff I figured out

    There are some caveats, but the Anker is the best way that I’ve discovered.

    • If you’re using the laptop heavily while the Anker is plugged in, the laptop battery will still lose charge, but much more slowly than on battery alone
    • If you’re using the laptop lightly while the Anker, the battery level will stay the same or charge slightly
    • If the laptop’s sleeping, the battery will charge, but slower than the normal power adapter
    • The 15-inch Pro is a different story because it has a) a larger screen, and b) different GPUs that draw more power. I expect that this means the 15-inch will lose charge under light usage while plugged in to the pack, but more slowly than without. I’d also expect that the laptop would charge while sleeping, although it will take longer
    • My anecdotal data is back up by the specs. The 12-inch MacBook Adorable (which is referenced by the Anker page) has a 41.4-watt-hour battery with a 29W power adapter. The 13-inch Pro gives 49.2-watt-hours with a 61W adapter. The 15-inch Pro has a 76.0-watt-hour battery and a 87W adapter. The Anker PowerCore over USB-C gives 5V at 3A, i.e. 15W of output.
    • The Anker detailed specs page mentions it’s not “fully compatible” but I expect that this is just because it charges more slowly than most people would expect

    Useful pages I discovered while researching

  5. Vanilla: Hide menu bar icons on your Mac for free

    I recently released Vanilla, a free app that lets you hide menu bar icons on your Mac.

    I had a bunch of people asking to hide the Rocket menu bar icon, but I didn’t want to add an extra option to Rocket’s already-crowded preferences window.

    There are other apps out there that already do this (I love Bartender!) but it felt weird recommending people download an app that costs $15 when Rocket was free. So I set about figuring out whether an app to hide menu bar icons is something people even wanted. This link took you to a simple page on my site that explained the idea and told people to tweet me if they wanted it.

    Rocket preferences

    Testing the potential for Vanilla

    A few people followed up on this, so I decided to build the app.

    I’m flipping back through my notebook and thought it might be kind of interesting to post up some photos (and also because I’m going to throw this notebook away soon but don’t want to lose the photos).



    There’s an annoying limitation in Rocket where, for certain apps that don’t properly implement the macOS accessibility API, it’s impossible to figure out the caret location to position the shortcut window. However, the system emoji picker doesn’t have this limitation. Why? I picked up my disassembler and started poking around the system frameworks.

    My best guess is that the system emoji positioner runs as a framework inside the current application. I dug around a bit, and found the macOS Open Scripting Architecture which lets you do that, but I couldn’t get it to work right. Anyway, while I was disassembling I also had a look at the system’s window server, which is responsible for showing stuff in the menu bar.

    Notebook p 93

    Disassembling, and then aha!.

    Take a look right at the bottom of that photo though—”can we just widen & shrink the status bar’s view”? That’s probably the “aha!” moment. I realised we could do a neat little hack with a perfectly coloured window to hide some menu bar icons.


    Anyway, I figured that was enough to build an app on, and away I went.

    Notebook p 106

    Lots of mental energy


    Things start to get ruthless on this next page: I cut a bunch of features and figure out exactly what it’ll take to get this app built quickly.

    Features

    Prioritising some features.
    ”$” is paid upgrades, “W” is web or marketing, “C” is core experience.

    Interesting note on “customisable icons” (a crossed out item in the top left column). I was dead-set on this being a core part of the Pro upgrade, and that no one would upgrade without it. But I decided to cut it from the 1.0 to get it out quickly. Guess what? Not a single person has asked for that feature since launch. Maybe that’s obvious in retrospect, but I was 100% certain this would be an important feature. Pretty glad I avoided that one.


    Also by this point I’d rewritten the core of Vanilla about ten times to get the effect and animations right. Check the right hand page—I must have decided to set a goal.

    Notebook p 106

    “Zen as fuck.”


    An early attempt at an app icon. Look at this piece of shit.

    Early app icon

    Gross


    This is where I did 95% of the work on Vanilla in the early mornings before work. Those of you with a good memory for buggy software will know that Vanilla’s 1.0 was terrible at multi-monitor support. This is why.

    Notebook p 106

    Probably not the most ideal workspace


    Here’s where I figured it was good enough to release so that I could hit my launch deadline of the 2nd of May.

    Ready to ship

    Ready to ship


    Six updates later and a couple more core rewrites. I had tried to talk to a few designers throughout the process but no one was able to replicate the right filter and blur effects to get the background colour to match the menu bar exactly. So I finally decided to do some Computer Sciencing and write an inpainting algorithm to remove the menu bar’s text so we could always get the colouring spot on. It works pretty well.

    More work still to do on Vanilla but I wanted to get these photos up before I get rid of this notebook.

  6. Rocket: Slack-style Emoji Everywhere on your Mac

    Last week I released Rocket, a Mac app that gives you Slack-style emoji autocomplete everywhere you type on your Mac.

    rocket

    The launch of Rocket easily had the best reception for any app I’ve made—quite a dream launch. Some highlights:

    • Front page of Product Hunt with around 200 upvotes
    • ~2,200 downloads, ~1,300 installs
    • My tweet about it went a bit crazy, with like 130 retweets and a few hundred favs
    • Featured on iMore

    A couple of lowlights, now that I think about it:

    • the app auto-update integration I added doesn’t seem to be working in the 1.0… I think lots of people will never get to use the newer versions
    • the app wasn’t quite done when I decided to ship (I wasn’t expecting this response!)—the licensing stuff, the custom gifs and emojis, and a few bugs weren’t in there. This meant that I didn’t make any revenue off the launch (that’s okay though, the rush of the launch was good enough).

    A thought I had considering that this is my first launch that anyone could consider successful: even with being featured and all the tweets and everyone being so positive, say I had the licensing stuff in there, and say it was $6. Now let’s just say that 5% of the 1,300 people who installed the app got the upgrade (I reckon that’s a bit high, but we’ll go with it). That’s 65 people × $7 upgrade = $455. Even with a dream launch—how the hell does anyone make money off software? Maybe for my dream launch I didn’t have my dreams high enough?

    Anyway, I couldn’t be happier. These have a been very exciting days.

  7. Charter: Read the Swift Mailing Lists from your iPhone or iPad

    I’ve just released a new app called Charter. It’s an iOS client for reading the Swift mailing lists. It’s available for free on the App Store.

    I shipped the 1.0 for Charter way earlier than I normally would, so the first version isn’t that great. The good news is that work’s well underway for the next version. And it’s all being done in the open.

    I’m really looking forward to making this app better.

  8. How to Record Podcast Audio from Your iPhone or Mac for $150

    For a new podcast project, I’ve done a lot of microphone, preamp, and digital recorder research. This guide and review shows you how to record podcasts and audio from your iPhone or Mac with one set of gear, and with the best bang for buck sound quality.

    These were my requirements:

    • be able to record on the go (iPhone, Zoom, etc.)
    • be able to record from my Mac (or PC)
    • be able to record an XLR microphone to both of these devices
    • keep costs as low as possible
    • be able to upgrade different parts of the setup later (e.g. I might want a better mic, to switch to a Zoom, etc.)

    I was able to get this done for around $150 US (depending on Amazon prices at the time you order).

    Summary

    I’ll review each bit of podcasting equipment individually below, but here’s where I ended up after a tonne of research:

    A quick note: this probably isn’t the cheapest overall way to record your podcast, but this is the best way that I’ve found to be able to record from both iPhone and Mac without having two sets of gear, and where each piece of equipment is upgradeable later on. You might be better served by an iPhone-specific microphone (which I nearly ended up buying) and a USB mic for your computer. If you have a setup that other people might like, let me know on Twitter and I’ll add them to this post.



    I make Transducer, a Mac app for posting your podcast to Libsyn or SoundCloud. If this guide helps you, please consider giving it a download—there’s a 20-day free trial, and it’s only $5 after that.



    Audio sample using the iRig Pro and Pyle PDMIC58

    Here is an episode of my podcast that we recorded via Skype using the iRig Pro and Pyle PDMIC58. We were pretty happy with the sound quality considering that each host has very little room treatment. We found that this audio quality was comparable to (if not better than) another episode we recorded using a Rode podcaster microphone.

    iRig Pro review for podcasting

    The iRig Pro is a really flexible audio interface that lets you connect an XLR microphone to your iPhone or computer for a pretty reasonable cost ($135 on Amazon at time of writing).

    Digital recorders, like the Zoom H4n, are the iRig’s main competitor, but those recorders don’t let you record to your phone (and only some of them can be used with computers). They’re also much, much more expensive than the iRig.

    Pros

    • The iRig can be used with both iPhone and Mac. I don’t know many other devices that can do this!
    • Works with any XLR microphone (though I wouldn’t put a mic that required a tonne of gain on it)
    • The iRig itself is really compact and light—much lighter than I anticipated
    • Recording is really simple for both iPhone and Mac. It’s more or less plug and play, with a little bit of software that I’ll go into in its own section
    • Audio recordings have good sound quality as long as you don’t turn the iRig’s gain above 3 o’clock (any higher you start to get a lot of noise). Thankfully, I found 3 o’clock a pretty comfortable position for spoken word audio recording. You’ll need to remove noise and increase the levels after the recording, but using Audition I found that this didn’t introduce any extra noise to the recording.

    Cons

    • The iRig uses these totally bizarre first party cables that I’ve never seen anywhere else… I’m terrified of losing them!
    • You can’t use headphones that have an inline mic to monitor sound (I’m guessing the iPhone picks the headphones’ mic over the one to the Lightning port). There’s also a little delay when monitoring your voice with headphones.
    • It can be a little ungainly to hold, walk, and talk at the same time with all the cords going everywhere

    Overall, the iRig solves a problem that not many other devices are solving, and does it very well. I was pretty skeptical going into the purchase (no one seems to be using iRigs for podcasting), but I was pleasantly surprised. It’s not perfect, but it’s a good solution that fits my needs.

    Pyle Pro PDMIC58 microphone review for podcasting

    The Pyle-Pro PDMIC58 is a dynamic microphone that provides unfathomably good value for money, running at around $15 on Amazon. This is a purchase that comes via Marco Arment’s microphone mega-review. If you don’t have one, you’ll need a pop filter—I got this Shure one for like $5 that does the job. Another thing to note is that this microphone doesn’t come with an XLR cable. If you’re thinking of recording while walking around, I’d recommend a short XLR cable or getting some velcro zip ties to coil up the cord while on the move.

    Pros

    • Cheap cheap cheap
    • Good sound quality

    Cons

    • Doesn’t come with an XLR cable
    • Build quality is average

    Overall, the way I’d describe the Pyle is that the build quality is what you’d expect for $15, but the sound is worth 4x that. This is a great value purchase, and it can be easily swapped out for a better XLR microphone later on. I’d even get one just as a backup microphone they’re such good value.

    The best iPhone app for recording a podcast from your iPhone

    I tried as many of the available iPhone audio recording apps as I could get my hands on. Most of them are bad to decent, but the best I found was Apple’s Voice Memos, which comes with the phone. For recording on the Mac with the iRig and Pyle, you can just use QuickTime—the iRig can be used like any other USB audio input, which is a great feature.

    Pros

    • Really easy to use and to start recording quickly
    • Simple to export many recordings at once by connecting to iTunes (some of the other apps had really terrible export options)
    • Works “through” the lock screen—i.e. you can start recording, lock your phone, and recording will keep going (and the phone even gives you live levels and recording progress on the lock screen). This was an awesome surprise when I discovered it!
    • Allows pausing and resuming a recording
    • Comes free with the phone

    Cons

    • You have to give stuff a name when saving, where the default is “Voice Recording #x”. Not a big deal, but a little annoying when you’re trying to record a few clips quickly

    Here are the other apps that I tried:

    • Apple’s Music Memos. This is a new app that does a reasonably good job, but missing some of the awesome features of Voice Memos. One thing this app does really well is boosting voice, so if you ever forget your microphone, I’d consider recording with this app as a last resort.
    • Voice Recorder
    • Awesome Voice Recorder
    • Voice Record Pro 7
    • Voice Record Pro
    • iRig Recorder. This is the option that the makers of the iRig offer. It doesn’t do anything really special.

    Conclusion

    With the iRig Pro for $135 on Amazon and the Pyle-Pro PDMIC58 for $15 on Amazon I was able to create a mobile and desktop podcast recording setup.

  9. Transducer 1.0

    I’ve been working on a Mac app that makes posting podcasts to Libsyn and SoundCloud way easier. This is the first Mac app I’ve ever made, and I’ve just released the first version. Download Transducer for OS X for free and let me know what you think.

    This started as a cobbled together Shell script, and has grown pretty organically from there. First, I just wanted a way to automate posting a new podcast episode to a Jekyll blog. Then, I wanted to get the file’s metadata and have that automatically filled in for the RSS feed. Then, I wanted to set the ID3 metadata, and to not have to type the same stuff out week after week.

    The 1.0 gives me exactly the workflow I wanted:

    1. Choose the audio file you want to post
    2. Choose the podcast you’re posting it for
    3. Fill in some metadata (title, description, etc.)
    4. Upload to Libsyn (or SoundCloud!)
    5. Run a custom script to create a Jekyll post that’ll eventually end up in the podcast’s RSS feed

    The design’s definitely not as polished as I’d like, and there are still some rough edges, but I’m hoping it’ll make posting a podcast a little bit easier.

  10. Protocol Oriented Programming in the Real World

    This weekend, I rewrote most of Locksmith, my library for using the iOS keychain, to be protocol-oriented. This was a fascinating process, and one that isn’t yet finished.

    Why?

    The primary reason I tried out a protocol-oriented approach was to manage complexity in a type-safe way.

    The big problem with the iOS keychain is the sheer complexity of it. There are five types of keychain items: generic passwords, internet passwords, certificates, keys, and identities. For each of these, you have four operations: create, read, update, and delete. That’s 20 operations, all with different attributes that need to be set and things that can go wrong.

    The way I thought about it, we have customization on two axes: types of items, and operations on items.

    To accomplish this, the actual Cocoa implementation uses a bunch of string constants and difficult to remember key/value combinations. This works, but it’s not user-friendly. You don’t know what’s gone wrong and why, and you never know the expected type of something without diving for the docs.

    With Locksmith, I wanted to have the same power as the Cocoa implementation, but in a way that made use of the type system and felt Swift-native.

    What do you get out of protocols?

    A couple of awesome things emerge when you focus on protocols

    • you can add functionality in new dimensions to existing types
    • you can easily adapt a rapidly growing API
    • you can decouple certain parts of your API for flexibility and testing

    Dimensions

    Say we have a Twitter account, which is a struct. And let’s say that we want to be able to save the username and password for that struct to the keychain.

    struct TwitterAccount {
    let username: String
    let password: String
    }

    In the past, we might’ve added a method to this struct to save it to the keychain.

    struct TwitterAccount {
    let username: String
    let password: String

    func saveToKeychain() throws {
    try Locksmith.saveData(["username": username, "password": password], forUserAccount: "username", inService: "Twitter")
    }
    }

    This is okay, but there’s a lot we don’t know about a given TwitterAccount from its declaration. Plus, we’re a bit limited by what that library provides to us.

    But with Locksmith’s new protocol oriented design, we get some nice functionality for free.

    struct TwitterAccount: CreateableSecureStorable, GenericPasswordSecureStorable {
    let username: String
    let password: String

    // Required for `GenericPasswordSecureStorable`
    let service = "Twitter"
    var account: String { return username }

    // Required for `CreateableSecureStorable`
    var data: [String: AnyObject] {
    return ["password": password]
    }
    }

    And with the method we get from Createable, we can save our item

    let t = TwitterAccount(username: "_matthewpalmer", password: "my_password")
    try t.saveInKeychain()

    Oh, and guess what… if we conform to Readable and Deleteable on that struct (which have no additional requirements), then we can use readFromKeychain() and deleteFromKeychain without adding any other code!

    struct TwitterAccount: GenericPasswordSecureStorable,
    CreateableSecureStorable,
    ReadableSecureStorable,
    DeleteableSecureStorable {
    // ...
    }

    let t = TwitterAccount(username: "_matthewpalmer", password: "my_password")
    try t.saveInKeychain()
    // For free!
    let result = t.readFromKeychain()
    try t.deleteFromKeychain()

    That’s really awesome. It almost feels like using mixins or stylesheets in CSS.

    Consider this as well: in the first instance, we conformed to two protocols. One for Createable, which works for anything that can provide data, and one for GenericPassword, which works for anything that belongs to a service and has an account.

    Two axes of customization.

    Imagine a 4×5 chessboard, where for each square on the bottom you have one of our actions: create, read, update, and delete. On the vertical, you’ve got a square for each type of item: generic password, internet password, certificate, key, and identity.

    20 different permutations of closely-related stuff is tough to model. But with protocols and protocol extensions, it becomes so much easier. With protocol extensions, protocols add functionality in new dimensions.

    That’s cool, but it’s probably not clear just how cool that really is. Let me tell you one more thing.

    We’ve seen that generic passwords have a service and an account. Those are required. What I didn’t show you was that generic passwords can also have creationDate, modificationDate, description, comment, creator, label, type, isInvisible, and isNegative. (And some of them don’t have the type you’d expect!)

    Let’s extend our TwitterAccount to use some of these.

    struct TwitterAccount: CreateableSecureStorable, GenericPasswordSecureStorable {
    let username: String
    let password: String

    // Required for `GenericPasswordSecureStorable`
    let service = "Twitter"
    var account: String { return username }

    // Required for `CreateableSecureStorable`
    var data: [String: AnyObject] {
    return ["password": password]
    }

    // Optional for `GenericPasswordSecureStorable`
    let creationDate: NSDate? = NSDate()
    let description: String? = "A Twitter account"
    let type: UInt? = 13
    let comment: String? = "Woah, this is complicated."
    }

    Too easy! We just added the properties onto our type.

    But wait… if we wanted to use the old static func approach, how would we do that?

    You might create methods that have optional or default arguments, but that explodes with complexity really quickly.

    Or you could pass around a dictionary and check against some agreed-upon keys, but then you don’t get the type system working for you. You’d never know what was required and what was optional, and it’s impossible to know for sure at compile time.

    Protocol oriented programming is the best approach I can think of to deal with this complexity and configurability.

    When I was first implementing this, I realised we weren’t actually returning anything useful from our readFromKeychain(). We were giving people a [String: AnyObject], which is barely a step up from where we started!

    We needed a nice type for returning data, but we also had to communicate to users that the metadata returned from a GenericPassword operation wouldn’t be the same as that returned from an InternetPassword operation—and they had to be able to know that at compile time.

    Sounds like a huge pain.

    Having protocols all the way down made it super easy to mix together the right type to return to users—we developed a ResultType, and created a couple of other protocols (GenericPasswordResultType and InternetPasswordResultType) that shared certain properties, but also provided their own unique properties.

    Plus, having this ResultType meant that we could provide actual types for the metadata we get back from the keychain—if the user saves an NSDate as metadata, they’re going to get an NSDate back. Wonderful—and almost impossible without protocols.

    Testing

    The WWDC session on protocol oriented programming mentioned testing, but it was a point that I didn’t notice at the time.

    Initially, I found that similar operations needed slightly different ways of actually performing the request (SecItemAdd vs SecItemCopyMatching, etc.). To help with code reuse, I introduced a closure on the root protocol: var performRequestClosure: (requestReference: CFDictionaryRef, inout result: AnyObject?) -> (OSStatus) { get }. Hairy.

    This started as an internal implementation detail, and became a super useful aspect of the library.

    First, it provides another point of customization, where users can change how or where certain items will be stored. If someone wants to store their type somewhere other than the iOS keychain, it’s really easy for them to do that. I use this internally in Locksmith, so that we can customize the options for a request in shared code, and then perform the request in code unique to the implementer. Very useful.

    Second, and following from the first point, we can override performRequestClosure to get access to the serialized request, and make sure we’ve added our attributes properly.

    We implement validation of the request to be performed in the closure—we take the requestReference, convert it to an NSDictionary, and check that all of the required attributes have been set.

    // Within `performRequestClosure`
    let request = requestReference as NSDictionary
    let creator = request[String(kSecAttrCreator)] as! CFNumberRef
    XCTAssertEqual(creator as UInt, expectedCreator)

    // ...

    That means we can easily and thoroughly test that all of the desired properties have been set, but without using mocks and relying on internal implementation!

    Wrap up

    There’s a lot to be liked about protocol oriented programming, but the big thing for me is the feeling that I still have a tonne to learn. This was my first crack at it, so if you have feedback or suggestions, feel free to contact me on Twitter.

    This was a very design-focused post. If you want to see how it’s actually implemented, check out the Locksmith Github repository.

  11. Visit the archive for more posts.