It’s been a while since I last worked on any mobile apps, so I thought the last couple weeks of sabbatical would be a good time to get caught up on iOS and specifically to learn Swift, which didn’t exist last time 🙃. For the most part, it was pretty easy to pick up and I was able to move fairly quickly on some apps I had been thinking about.
One of the only problems I ran into was related to Core Data concurrency. Specifically, if two different threads are reading and writing data, you get errors like 'NSGenericException', reason: Collection <__NSArrayM: 0x7fabb400> was mutated while being enumerated.
The solution is private queue contexts. I won’t do a full explanation of queue contexts here, but the Apple Developer Documentation has some good information. The idea is to create a private context to operate on while we’re doing background work.
For this to work as expected there are a few things that need to happen:
Set context.parent. In order for the changes to eventually be written to disk, we have to associate the new, private context with the main context by setting newContext.parent = oldContext.
Use context.object(with: objectID) to make core data relationships. We need to get a reference in the current context to any objects that were created outside the context.
After saving, we also need to save the parent context to commit the changes to disk. To make it thread safe, we use oldContext.perform or oldContext.performAndWait depending on whether is should be asynchronous or not.
I put together a gist to demonstrate:
The following articles were especially helpful to understand how to fix this problem in my case:
I occasionally use git bisect to figure out where I’ve introduced test failures. If you’re not familiar, given known good and bad commits, along with a test command, git bisect does a binary search over your repo to determine where a bug or test failure was introduced. This is especially useful on large repos with a test suite that takes a minute or two (or more 🙃) to run.
Most of the time, I just need to check the last handful of commits. To that end, I’ve written a bash function that assumes the current HEAD is bad, 10 commits prior is good, and automatically runs a test command that you define.
git bisect start
git bisect bad
git checkout HEAD~10
git bisect good
git bisect run "$@"
This won’t cover every case, but should help automate this fairly verbose process most of the time.
I’ve been dabbling in Golang on and off for a little while now. Recently I was looking for a package to read and parse configuration files with the following requirements in mind:
Use environment variables and JSON files (in that order).
Support hot reloading.
I looked at some of the popular configuration packages, but didn’t see anything that I loved. Many of them don’t meet the requirements I had in mind or are more complex than I’d like.
So, I decided to write config — I know, it’s a great name. It’s pretty simple. We cache values in memory to minimize disk IO. On SIGHUP (or any time you call config.Reload()), we clear the cache, so you can update the configuration without restarting your app.
I’ve been playing with Github Auto Deploys recently. There are a couple things I’m doing here that I think are different from the typical auto deploy workflow.
Using the deployment event. Github has a way to differentiate push from deployment. Deployments have the added benefit of depending on Github statuses, like ci/travis-ci. Having deployments depend on a test suite is nice.
Using git fetch && git checkout. Instead of doing a git pull and slowly updating files depending on the network speed, first fetch all the files and then do a quick file pointer swap to instantly update all files at once.
Photon, the image service hosted by Automattic, does lossless compression automatically. Page Speed will probably still complain that images aren’t compressed enough. Luckily, Photon has a way to fix that.
There are a couple of parameters, quality and strip, that will further reduce the file size of JPEG images. Quality is pretty straight forward. The strip parameter will let you strip EXIF and color data. I use a snippet like this to set the quality to 80% on my site.
The results can be pretty dramatic. At full size, this image of downtown Madison goes from 16MB to 2.7MB by setting the quality to 80%. That’s a big deal on a mobile connection and it’s pretty hard to spot the difference on most images unless you’re looking at them side by side.