Most of the apps I prefer have a few common characteristics. They keep up with the latest OS features, are designed with “best practices” in mind, and are native to the platform (e.g. they don’t have to be built by the OS provided frameworks but they must look and behave like a native OS app).

If I were to list my current top 5 iOS apps, they would have to be the following:

1Password

1Password is my go-to password app. I have a subscription, and it is truly a best of class app. It keeps up with the latest iOS features like iOS 12 Password Autofill. If you don’t have a password manager, it is the one universal recommendation I can make. 1Password also is avaiable for macOS, Windows, and Android.

OmniFocus

OmniFocus is perhaps the app I use the most. With OmniFocus 3, the switch from Getting Things Done contexts to more useful tags, it is everything I want in a to-do app. It handles complex repeats, has a special Today tag for items that aren’t due but you want to work on, etc. It is a bit pricey, but the major version upgrades are only every few years. While there are obviously many competitors, OmniFocus keeps up with iOS and macOS features. OmniFocus offers many complex features such as perspectives which helps manage my to-do list while still being usable.

Overcast

Overcast is my podcast player of choice. The Smart Speed feature which basically skips silence, and the Voice Boost feature which helps make sure the sound is loud and clear.

Soulver

Soulver is a notepad calculator. While I actually use the macOS version much more than the iOS version, I still find the iOS version useful every now and then. Basically, it is the way a calculator app should be. Once you try it, you won’t ever want to use a “normal” calculator ever again.

MindNode

MindNode is a mind mapping app. If you’ve never used a mindmapping app, it is a great way to quickly jot down, visualize, and expand on ideas.

Modern Auto Layout is the most up-to-date book about the Auto Layout system from Apple. It does not assume any previous knowledge on laying out your UI for your Mac or iOS apps. It also covers both Interface Builder and programmatic ways to lay out your UI.

Hands down, it is the best book I’ve found which covers all modern practices such as how to use scroll views with Auto Layout, how to use stack views, dynamic type, and more. Of course, coming from the author of Use Your Loaf who has written numerous blog posts about the subject, it is not a surprise that the subject is covered well. Even common bugs are discussed as well as workarounds.

I think even advanced users of Auto Layout may learn at least one or two things, but it is heartily recommended. I wish I had this book when I was starting to use Auto Layout.

Hugo has an asset pipeline feature which can basically get an asset resource file, manipulate it (e.g. compress it, concatenate it, etc.), and then generate a final output file. I imagine most people use it for CSS and JavaScript where they minify the source, fingerprint the resource (e.g. calculate the SHA sum of the contents) and then publish the generated file. (Embedding a hash of a file into a resource’s URL works great for caching since you can add the appropriate headers and ask the browser to cache that effectively unique URL forever. When your resource changes, the resource URL will change because the generated hash in the file will be different.)

In order to make things fast, Hugo caches aggressively. So if it sees that the contents of your file has changed, it will re-build the asset. Unfortunately, my issue was that I had an asset (say asset S which is an SVG file) which included a link to another generated resource. In short, it depended on the generation of another asset (say asset C which is a CSS file). Hugo would not recognize the dependency. So if I made changes to the CSS in asset C, Hugo would re-build asset C but not my SVG asset S with the new link to C. If I made changes to asset S, it would then update with the latest link to asset C.

It was somewhat annoying but understandable why this issue exists. The solution I settled on was varying the final output path of asset S based on the final output path of asset C. By varying the output path, a newly generated asset S would be created if C were to change.

Here’s the sample code with an image SVG (e.g asset S) linking to a CSS stylesheet and the template code which was building the SVG. The custom.scss is just a random stylesheet.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<?xml-stylesheet type="text/css" href="{{ .style_link }}" ?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- ... -->
</svg>
{{- $style := resources.Get "custom.scss" | resources.ToCSS | resources.Fingerprint -}}
{{- $linkSVG := resources.Get "image.svg" | resources.ExecuteAsTemplate (printf "image-%s.svg" (index (split (path.Base $style.Permalink) ".") 1)) (dict "page" . "style_link" $style.Permalink) | resources.Fingerprint -}}

{{ $linkSVG.Permalink }}

The final SVG output file would take the fingerprint from the generated CSS file and use the CSS fingerprint in its own filename. Not exactly the prettiest solution (it effectively becomes image-<css fingerprint>.<svg fingerprint>.svg which is a long filename), but it’s a way to force the pipeline to re-generate assets with hidden dependencies.