360iDev was once again informative and inspirational.

This year, for me, was more inspirational than informative, which is not necessarily bad, but I think just a symptom of my session choices. I’ve included a list below of the sessions I attended and would recommend, and then sessions I didn’t attend but wanted to.

They are still working on transcoding all the session videos (which they put online for everyone for free!) so check back for updates.

Recommended Sessions

These are sessions I attended which are worth watching. I’ve filtered out the sessions which didn’t inspire or weren’t technically interesting (to me).

  • Something Deep With Mike
    Mike Lee (@bmf) talks about world modeling, how the models predict our current global situation, and what we can do as software engineers to aid in the shaping of our planet’s future.

    This is a must watch presentation. My potentially inadequate description might make this talk sound like something you can skip, but that is entirely not correct. The concepts and information presented here are so important and relavent that this should be mandatory viewing for everyone.

    The 360iDev version of Mike’s presentation is more refined and to the point than his UIKonf discussion, but YouTube has Mike’s “World Modelling” UIKonf video online at this time and is worth watching.

  • Decision Fatigue
    Daniel Haight (@Daniel1of1) gives us an interesting and informative look at how humans make decisions.

    Decision Fatigue is the name given to the effect in which the quality of your decision making deteriorates with the number of decisions you have to make.

    What is interesting is that many studies have shown that the difficulty of the decisions actually have little effect on the rate of the deterioration, more so the quantity. This is to say that having to make a lot of ‘small’ or ‘easy’ decisions can seriously harm the quality of the ‘bigger’ decisions you make.

    Have you ever had to repeatedly decide how you might implement an API design? How you’d implement a network layer? K&R braces? tabs or spaces? withCompletionBlock: or just completionBlock:? Each of these decisions especially when made over and over can take away from the much more important decisions along the lines of “What is the ultimate goal of what we’re building?” or “Why are we implementing this?”

  • Switching Your Brain to Swift
    Greg Heo (@gregheo) gives a compelling and well presented talk which primed me to get more into Swift.
    [video] [blog]

    We’re now a year into Swift. For those coming from Objective-C who are still testing the Swift waters, what do you need to do to switch your brain over to the new Swift way of thinking? What’s new, what’s the same, and what’s completely different when programming for the same platform in a new language? Big-picture outline: – focus on safety – undefined behavior – less dynamic behavior and fuzziness; more strong typing and predictability – a little bit on Swift/Obj-C interop and how to make the transition

  • Bringing Swift into your Objective-C Projects
    René Cacheaux (@RCachATX) delivers some really awesome advice about best practices for moving over to Swift.

    Join us as we explore tips and tricks for introducing Swift source into Objective-C projects. We’ll cover where in the networking-model-UI stack to begin writing Swift, how to maximize the benefits of using Swift without re-writing your apps, and how to avoid some of the common pitfalls getting Swift and Objective-C working harmoniously together.

  • iOS Testing: Beyond the Model
    Cate Huston (@catehstn) gave an inspired session about how to better implement testing in a MVC structured GUI app.
    [video] [blog]

    Unit testing on iOS has always been a challenge, mainly because the ViewController creates a mix of UI and non-UI code. But, it’s totally possible to achieve good levels of coverage on view code for iOS, and this talk will cover some strategies for doing so, focusing on a real app (no contrived examples here!) Including: splitting up a ViewController to make a seam, verifying button actions, dealing with [self navigationController], handling asynchronous code, and how we can compare UIImages.

  • Good Intentions II: Enemy of the State
    Jay Thrash (@jaythrash) gives a very interesting proposal about using a state machine to organize app flow and to clean up View Controllers.
    [video]

    In a world where ViewControllers shoulder the burden of managing ever-changing vagarities of application state logic and complex navigation stacks, one design pattern emerges from the past to lead us toward a better, brighter, and lighter future of app development.

    In this sequel to last year’s blockbuster presentation, “Good Intentions: Building Better ViewControllers”, we will revive a venerable programming technique for explicitly defining application behaviors and thereby reducing the responsibilities of our much maligned ViewControllers.

“TODO” Sessions

I didn’t attend these due to overlap in the schedule, but they sound like sessions which shouldn’t be missed.

  • Fancy Custom Transitions
    Grant Davis (@gravitybytes)
    [video]

    Develop powerful, beautiful custom transitions using the APIs introduced in iOS7. In this session we’ll explore how to make both simple animated custom transitions as well as more complicated, interactive transitions.

  • Solving Auto Layout Problems
    Jack Cox

    Auto layout is hard. It requires developers to think different about structuring and manipulating views. If the developer doesn’t express themselves 100% correctly the results can be messy. And auto layout doesn’t help with it’s obtuse error message and verbose messages. This talk will cover some uses of auto layout that bedevil developers like: using auto layout in scroll views, self sizing tables and collections, and debugging conflicts.

  • Apple Pay: What happens when you tap?
    Stepan Hruda (@stepanhruda)
    [video]

    Arguably Apple Pay might be the nudge that NFC needed to go mainstream. Let’s talk some implementation details of what happens when you tap your iPhone or Apple Watch and why tokenization is a $20 word for a 5-cent software concept.

    We’ll cover the basics of credit cards, NFC and in-app Apple Pay payments.

  • Mastering Auto Layout
    Justin Williams (@justin)
    [video]

    The third-part of Justin’s 360iDev Auto Layout trilogy! Learn how to take full advantage of Apple’s modern layout toolkit in your iOS 9 and OS X El Capitan apps. Justin will walk you through crafting custom interface elements using Auto Layout, layout anchors, dynamically sized elements, keeping your sanity with size classes, and Swift 2.

  • Building Habits: keeping users engaged
    Sally Shepard (@mostgood)
    [slides]

    So you’ve got some downloads but downloads don’t necessarily equate to active users. How can you engage a first time user? How can you keep them coming back to your app? The psychology of building habits

    • Joyful first experiences
    • The awesome power of email
    • Deep-linking
    • Pushing for good
    • Helpful help sections

Game Jam

As usual, this year I participated in the “Game Jam” on Tuesday night. Since the idea of the game jam has transitioned from building an actual game to more of a “stay up late and code on something” feel, I take the opportunity to build something I wouldn’t normally get a chance to play with. This year I chose to attempt to build a “cheat app” for a word game called Capitals (which is pretty fun).

The idea sounds simple enough… take a screen shot, run it through an Optical Character Recognition (OCR) process to identify the available letters, then pass those letters into an anagram algorithm to produce a list of possible words.

I might write up a more detailed post on my findings, but the short version is that I spent most of my time trying to get the OCR engine, Tesseract to recognize the characters in the screen shot. With some help from fellow 360iDev attendees I eventually managed to get the engine to recognize 90 percent of the letters… not good enough. So the idea didn’t merit a demo at the Gam Jam review, and is “on the shelf” for future attempts.

Con-clusion

The 360iDev conference has always been about the people and the community. This year was no exception. We, as iOS developers, have a great community with many very smart and open people in it. As with any community I care about, these are the tenets I try to follow:

  • Be kind and supportive
  • Contribute
  • Be thoughtful
  • Take responsibility

Cheers,

Levi


Updated September 3, 2015 with additional video and blog links.

While talking with my girls about the weather, we noticed the weather forecast on Sarah’s phone and saw an icon of the moon and stars, and I had to explain a few things.

  1. It bothers me that “night time” is commonly represented by an icon of the moon. The moon is out durring the day just as much as it is out durring the night.
  2. Often icons like this represent the moon as a crescent, and there’s stars inside the concave part of the crescent. This is implying that the star is in front of the moon.

Do an image search for “night time weather icon” and you’ll see plenty which look like this:
night icon

So I mentioned that we’d be in big trouble if there was a star in front of the moon, and started to try to explain that many stars are much like our sun, and our sun is very big and very hot and if it was close enough to be between us and the moon like in the icon, we’d be toast.

But then I balked in my explanation, because I wasn’t sure what the relative size of the sun was to our lunar orbit. I didn’t know if the sun would actually fit inside the orbit of the moon (regardless of the consequences). So I had to look it up, and then make this graphic to get an idea of the relative sizes:

size of our sun
Click/Tap on the image for a different look at higher resolution (can you see the moon!?). Original image credit: NASA

Yeah, no way the sun is fitting between the Earth and Moon. In fact, the sun is about 3.6 times as big as the distance between the Earth and moon!

Our sun is so big, if the Earth was in the center of a ball the diameter of the Moon’s orbit, the Sun could almost hold two of these balls side by side!

The details:
Our sun is 1,391,684 km in diameter (1712 pixels). [Sun]
The Earth is 12,742 km in diameter (~16 pixels). [Earth]
The Moon is 3 474.8 km in diameter (~4 pixels). [Moon]
The average distance from the center of the Earth to the center of the moon is 384,400 km (~473 pixels). [ref])
* Please note, all pixel size references are to the full scale image

1,391,684 km / (384,400 km x 2) = 1.81

The Sun is 1.81 times as big as the average diameter of the Moon’s orbit around Earth!

WOW, the sun is big.

Now that we know what the relative size of the Sun is to the Lunar Orbit, take a look at this for an idea of how big (or small!) our sun is in general.


Revised June 19 2015, with updated graphic, edited content, and inclusion of sun comparison link (thanks Bob).

A UIImage category which provides “visible” pixel cropping capabilities.

A given image can be rectangularly cropped based on calculated insets to “visible” pixels. Visible pixels are those whose alpha component are greater than or equal to a given alpha threshold.

Available on github: https://github.com/levigroker/GRKImageCrop

demo

Installing

If you’re using CocoPods it’s as simple as adding this to your Podfile:

pod 'GRKImageCrop'

otherwise, simply add the contents of the GRKImageCrop subdirectory to your project.

Documentation

To use, simply import UIImage+GRKImageCrop.h:

#import "UIImage+GRKImageCrop.h"

Then you can use the category to create a cropped image from a given image:

[image cropImageBelowAlphaThreshold:0.0f completion:^(UIImage *croppedImage, NSError *error) {
    if (croppedImage)
    {
        //Use croppedImage
    }
    else
    {
        //Hanlde error
    }
}];

The only expected error would be memory related.

Additional documentation is available in UIImage+GRKImageCrop.h and example usage can be found in the GRKImageCropTestApp.

Disclaimer and Licence

CreateTextFileHere is a manually activated AppleScript applet used to create a text file at the current Finder location with BBEdit

This utility works in tandem with the ‘bbedit’ command line binary (which should already be installed and functional at /usr/local/bin/bbedit).

The intention is for this utility to be accessed from the currently active Finder window and acts on the current directory in the Finder. I suggest adding CreateTextFileHere.app to the a Finder window’s shelf (command-drag it into a Finder window at the top where the other tool icons are located) so it is available from the Finder as needed. Alternatively, it could be activated from the Script Menu.

Thanks to the kind folk over at Bare Bones Software for letting me use a modified version of their text document icon.

Everyone works in different ways and employ different tools to do the things they want to do. Here’s my curated list of tools I find I keep coming back to.

Development

Tower
The best Mac GUI git client I’ve tried.

CocoaPods
Third party code dependency manager.

Dash
Awesome documentation browser. Handles many languages and doc sets, but I use it primarily for Cocoa.

SimPholders 2
For finding and inspecting the contents of your app in the simulator.

iExplorer
For inspecting the contents of your app (or others) on-device, this is a great tool.

mogenerator
If you’re working with CoreData, you should be using this tool to abstract your object classes.

Fabric
iOS crash reporting, usage statistics, beta build distribution, and more.

Cocoa Rest Client
A simple GUI alternative to curl for testing ReST endpoints.

Cocoa JSON Editor
Super nice GUI tool for creating and editing JSON files.

licecap
Create animated gifs. Really nice for quick app demos on github.

Accessorizer
Great timesaver for generating boilerplate Objective C code, though Objective-C’s language updates have made this tool less useful than it used to be.

General

1Password
A secure vault for passwords, credit cards, passports, etc. Seriously the first thing I install on a new device.

Dropbox (referral link)
Secure online file storage and sharing. The second thing I install on a new machine, primarily to sync 1Password vaults and other app settings.

BBEdit
The text editor. I’ve been using this since… well since I can remember. It does it all and doesn’t get in your way. Installed almost immediately on a new machine.

Little Snitch
Basically a firewall for outgoing network connections. Probably the fourth thing I install on a new machine.

Quicksilver
A keyboard activated launcher and action performer (hard to describe). It is kind of like spotlight, but with more customizability and functionality.

Pocket
Bookmarking and reading app. Desktop, iOS, and web. A great way to keep hold of the gems one finds while surfing, Twitter, etc.

Soulver
Awesome calculator for problem solving.

Yummy FTP
The best FTP/SFTP Mac GUI client I have tried.

Knox
Simplifies creation and management of encrypted disk images. Everything that doesn’t go in 1Password goes in here.

Lingon
A GUI for creating and managing launchd configurations.

Name Mangler
Rename batches of files via a nice GUI.

Tweetbot
Twitter client for Mac and iOS.

Slack
Team collaboration and communication tool.

Airmail
The best, but not perfect, email client I have tried since giving up on Mail.app.

Backblaze (referral link)
Offsite painless backup solution.

Bartender
De-clutter your menu bar. This manages all the little menubar warts that seem to show up with various tools. Keeps things nicely tucked away, but accessable.

BetterTouchTool
A tool for configuring your interaction with a mouse or trackpad. Basically it allows you to program various gestures, clicks, taps, etc. to do any number of things.

cd to
A great little app which you install in your Finder “shelf” to open a terminal window at the current Finder location. It’s a huge timesaver if you are moving between the finder and Terminal a lot.
There’s an updated Yosemite icon (from https://github.com/jbtule/cdto/issues/9) which you’ll most likely want too.

CreateTextFileHere (shameless self promotion)
Another little app which sits in your Finder “shelf” to create a text file at the current Finder location. Created by yours truly.

Degrees
A little weather widget. I use the Mac menubar version. It’s nice and unobtrusive.

The Unarchiver
Far better tool than Mac OS X’s standard unarchiving tool. It handles so many more file formats.

Truly I want to like Xcode Bots, and I want them to work for my needs, but I got frustrated enough to tweet this not long ago:

3:45 PM MT - 3 Mar 2015 “I’m so done being bitten and frustrated with Xcode Bots. What a steaming pile. </rant>” -levigroker

This frustration was caused by the latest in a long line of frustrations and their workarounds. Specifically, our bots are now spontaneously failing because of this error:

“Failed to mmap. Could not write data: Invalid argument (-1)” build service error

(don’t be fooled by the “Fix It” button which doesn’t seem to)

I’m not the only one, as there are others on the Apple Dev Forums (login required) which are experiencing the same (or very similar) issue. The suggested workaround is to downgrade from Xcode 6.1.1 to 6.1. Yeah, I’m not about to do that, so our CI build is broken, and I’m left with no choice but to go back to Jenkins. Honestly, that kind of gives me a sense of relief since I know I can get Jenkins to perform all the tasks I need, and I know if our CI build breaks it will be my fault and not an external dependency like Xcode Bots, over which I have no control.

I mentioned a long line of frustrations with Xcode Bots, and that’s true. I’ve not taken the time to try to document them all, but here’s some off the top of my head:

  • In my post Xcode Bot Keychain Configuration I mentioned the fact that the bot server does not seem to fetch non-development provisioning profiles, and the steps needed to work around this issue.
  • Because of the aforementioned provisioning profile issue, we have never been able to get our Mac app build to work. We always get a provisioning profile mismatch error. We even went so far as to copy the developer cert and private key into the bot’s keychain…
  • Inexplicably, a CI build will fail, and automatically rebuild, which will then succeed.
  • If a build (“integration”) succeeds, we get two for the price of one (no idea why… no new commits triggered it).
  • The web UI is… gone? In previous builds of the Xcode Bot server there was a web UI which presented the details of each build. This was removed, so any truly useful information must be gathered from Xcode.
  • Tracking down build system issues is laborious and cumbersome. The only real source of valuable information is the raw “Build Log” file, which can be viewed from within Xcode, but only after the integration has finished (no “tail -f”-like behavior), but be prepared to wait and keep scrolling as this file loads, slowly, with no UI feedback from your remote build server.
  • In general, the internals of the Xcode Bot system are so black box and inaccessible that debugging the process, understanding how it works, or extending it, is a non-trivial time investment which I’d rather use to be working on actual projects.

After all this, I still have high hopes for Xcode Bots, I do want to like them, and I look forward to the day when I can use them for my needs. That day is not today, unfortunately.

The Xcode Bot server (as of 3.2.1) uses /Library/Developer/XcodeServer/Keychains/Portal.keychain to store the needed certs and keys used for codesigning (previously it used the System.keychain.

The server seems to only automatically download developement certs and profiles (not distribution) so we must manually populate the keychain with the dsitribution cert/key pairs needed and manually place the distribution profile(s) we need into the location which the server looks for them. In my iOSContinuousIntegration system I have a pre_action.sh script which handles copying the profiles from where they are committed in the repository to the proper location on the server for the bots to locate them, so no need to go into that here. The keychain is a bit more complicated…

(Shamelessly borrowed from http://stackoverflow.com/a/25934218/397210)

  1. Copy the Portal keychain to your desktop:

     sudo cp /Library/Developer/XcodeServer/Keychains/Portal.keychain ~/Desktop/
     Password: your-administrator-password
     sudo chown `whoami`:staff ~/Desktop/Portal.keychain 
    
  2. Set the Portal keychain password to “123”

     security set-keychain-password -o "`sudo cat /Library/Developer/XcodeServer/SharedSecrets/PortalKeychainSharedSecret`" ~/Desktop/Portal.keychain 
     New Password: 123
     Retype New Password: 123
    
  3. Open the Keychain in Keychain Access:

     open -b com.apple.keychainaccess ~/Desktop/Portal.keychain
    
  4. Unlock the “Portal” keychain using password “123” (This may not be needed as it may already be unlocked).

  5. Add the needed keys to the “Portal” keychain. Generally you will want your AdHoc Distribution certificate and private key, assuming you’re building for AdHoc distribution (for say, Crashlytics Beta).

  6. Make sure the private keys have the correct access rights (in the “Access Control” tab of the “Get Info” for the private keys in Keychain Access), “xcsbuildd”, “xcscontrol”, “xcodebuild” and “codesign” should be listed. “xcsbuildd”, “xcscontrol”, and “xcodebuild” are inside the Xcode binary… /Applications/Xcode.app/Contents/Developer/usr/bin while “codesign” is usr/bin/codesign. Finder’s “Go to Folder…” command is useful for locating these binaries. Though you will likely need to “unhide” the /usr directory from the GUI.

    This can be done by opening a terminal and issuing the command:

     sudo chflags nohidden /usr
    

    Then navigate to /usr/bin and select the codesign executable from the file picker GUI in the “Access Control List” tab of the Keychain Access’s Get Info dialog. Once added to the ACL you can (and should) re-hide /usr with this command:

     sudo chflags hidden /usr
    
  7. Lock the “Portal” keychain, quit “Keychain Access”

  8. Reset the Portal keychain password:

     security set-keychain-password -p "`sudo cat /Library/Developer/XcodeServer/SharedSecrets/PortalKeychainSharedSecret`" ~/Desktop/Portal.keychain 
     Password: your-administrator-password (optional step)  
     Old Password: 123
    

    It may or may not ask you for your administrator password again, pay attention to the prompt.

  9. Copy the Portal keychain back

       sudo chown _xcsbuildd:_xcs ~/Desktop/Portal.keychain
       sudo cp ~/Desktop/Portal.keychain /Library/Developer/XcodeServer/Keychains/
    
  10. Since the system caches open keychains, restart you computer.

…all this because Xcode Bots don’t copy non-development profiles.

Recently I’ve been reading up on Apple’s In-App Purchase system with the goal of understanding how to support various types of purchases. It seems to me that non-consumables are kind of the “poster child” in-app purchase, for the typical “remove adds” or “unlock content” models. Which makes sense, because, in-app purchases are pretty simple if you are talking about auto-renewing subscriptions, or non-consumable items. Simple because Apple sends you all the information you need in their receipt, and persists that information for you. The only thing you’re required to do is allow the user to “restore purchases” which basically gives you the receipt information back as if a purchase was made. Easy.

Things get more complicated when you want to handle the other types of purchases. Specifically consumables and non-renewing subscriptions. Apple pretty much says: “Here’s the receipt for your purchase… you better keep track of it for your user. Oh, and we’re never giving you this information again…” or at least that’s what it sounds like to me when reading through the “Persisting Using the App Receipt” section of the In-App Purchase Programming Guide

Where it says:

Information about consumable products and non-renewing subscriptions is added to the receipt when they’re paid for and remains in the receipt until you finish the transaction. After you finish the transaction, this information is removed the next time the receipt is updated—for example, the next time the user makes a purchase.

So that means, you, as the developer, must have your own server to maintain a record of these kinds of purchases, and allow a mechanism for your user to restore these kinds of purchases (on a new device, for instance). That means building and maintaining your own server to handle this, or integrate with something like Parse. Not the end of the world, but…

That’s kind of crummy.

Not only do you need to build/integrate with the server component, but now you must ask your users to create an account with your system so you can identify them to associate their purchases with their account. I’m sure users are used to this, but it’s still a drag.

So, I searched around and found this post which stated that non-renewing subscription information persisted in the receipt from Apple. Wait, what? This post is obviously crazy, the In-App Purchase Programming Guide said that didn’t happen…

But now, while reading through Apple’s Receipt Validation Programming Guide there’s this statement in the “In-App Purchase Receipt” section:

The in-app purchase receipt for a non-consumable product, auto-renewable subscription, non-renewing subscription, or free subscription remains in the receipt indefinitely.

Note the non-renewing subscription is listed as remaining “in the receipt indefinitely.”

So maybe that post wasn’t crazy, and we could use the receipt for non-renewing subscriptions(!) without the need for a server component. That’s super interesting…

…but you’re still out of luck if you want to deal in consumables.

P.S. I’ve provided Apple with this feedback for their In-App Purchase Programming Guide documentation; feel free to do so as well.

Like many developers, I would guess, I have many ssh keys. Keys for various services such as github, bitbucket, and others, each with the potential for multiple accounts. Managing these keys when using git on the command line can be a pain, but I’ve got a decent working solution.

ssh-agent

ssh-agent is a process that sits around and helps ssh do its thing on your behalf. There are several helper apps which allow you to configure its behavior, but specifically we are interested in ssh-add.

ssh-add is your friend, especially on Mac OS X.

It can be used to store credentials which, upon a connection attempt, ssh will use. ssh will try all the credentials in the list until it finds one which works.

You can get a listing of what keys are already “known” by the agent with ssh-add -l:

1
2
3
4
5
Moorea:~ levi$ ssh-add -l
2048 7d:81:16:54:ae:cb:9b:da:b6:65:75:32:40:c6:1e:ac /Users/levi/.ssh/progroker_id_rsa (RSA)
1024 b5:86:9e:05:d3:ba:f1:57:71:90:d0:2e:a9:94:1a:47 /Users/levi/.ssh/id_dsa (DSA)
2048 d4:f4:8c:be:2d:cd:5d:06:55:4a:24:bd:c1:9c:83:2b /Users/levi/.ssh/id_rsa_bitbucket (RSA)
Moorea:~ levi$ 

And here’s the awesome-sauce… you can add keys whose credentials get stored in the keychain with ssh-add -K <path_to_private_key>:

1
2
3
4
5
Moorea:~ levi$ ssh-add -K /Users/levi/.ssh/id_rsa_bitbucket
Enter passphrase for /Users/levi/.ssh/id_rsa_bitbucket:
Passphrase updated in keychain: /Users/levi/.ssh/id_rsa_bitbucket
Identity added: /Users/levi/.ssh/id_rsa_bitbucket (/Users/levi/.ssh/id_rsa_bitbucket)
Moorea:~ levi$ 

So, if your ssh key has a passphrase on it, that passphrase is now stored in your Mac OS X keychain, and when ssh is looking for credentials to make the connection with it can find the key and use it without you needing to enter your passphrase again.

Win.

HTTPS

Further, for bonus points, when you’re not using ssh, but rather https, you can still use the keychain…

Being on Mac OS X, we have the osxkeychain which can be used to store and retrive the kind of information we need for authentication.

To set this up, add (or ensure it is already there) the helper line in the [credential] section of your ~/.gitconfig file:

1
2
3
[credential]
        helper = osxkeychain
        useHttpPath = true

This will allow git to query the OS keychain when it is looking for stored credentials.

If you have multiple accounts on the same system, you may want to tie a set of credentials to the full repository path, so you can access different repositories with different credentials. That’s what the useHttpPath = true line does.

Now, once you authorize a connection to a specific repository those credentials will be stored in your keychain:

git keychain entries

Win a second time.

Having not posted anything here in quite some time I started to wonder “why not?” and discovered, after some introspection, that I have limited myself by considering this just a technical blog.

Often I would find myself with ideas for technical topics to write about, but faced with the daunting task of writing them up in a digestable format proved, obviously, too big a hurdle to overcome, and nothing actually got posted. So, I’m switching it up a bit.

While I’ll still happily write about technical topics which I come across, I also plan to delve into topics which are less technical, and perhaps even more of a personal or sociological nature.

With this change, I’ve also updated the visual theme here to be a bit lighter and less default.

I certainly hope to write more here, and I certainly hope others will appreciate that effort.

Cheers, and Happy Halloween!

Levi