CSVDecoder

I've just released a new Swift library!

Heavily inspired by Flight-School/RegularExpressionDecoder. I wanted to build my own decoder to help myself understand how Swift's Decoder actaully works.

So I chose one of the most simplest data formats and built CSVDecoder. There are plenty of improvements to me made, but for now, it works 🥳

Tidying Up Decodable Initialisers

Swift's type inference lets us remove the need to specify the type with every call to decodable 🥳

internal extension KeyedDecodingContainer
{
    internal func decode<T: Decodable>(_ key: KeyedDecodingContainer<K>.Key) throws -> T
    {
        return try self.decode(T.self, forKey: key)
    }
    
    internal func decodeIfPresent<T: Decodable>(_ key: KeyedDecodingContainer<K>.Key) throws -> T?
    {
        return try self.decodeIfPresent(T.self, forKey: key)
    }
}

2018 - Year In Review

Token Unplash Photo - by NordWood Themes / Unsplash

I'm now reaching the end of my second year freelancing and it’s been pretty much non stop.

You can check out my 2017 year in review here.

Clients

2017 left me with a nice long term retainer with a client that I still have today. I’m finding the perfect project combination for me is one large project plus one, maybe two, small projects or a side project. This works well because the large project can provide you with predictable income and generally be an awesome project that you can show off when it’s complete. The small projects will help you extend your “network” (word of mouth has become my best source of new projects) and, for me, help improve the way I try to sell my services (practice makes perfect!).

Compared to last year, where I worked with 8 different clients, this year I have worked with 5 different clients with the largest providing 75% of my turnover. Having one client make up 75% of my turnover is probably not the safest thing but to help counteract this I have made sure to put extra money into the rainy day fund.

Side Projects

Along with my open source projects (listed below) I've also worked with Hector on xPal; a tool for generating Xcode color asset catalogs from a Sketch file and Quids; which we brought back to life to be a Cryptocurrency manager.

Investments

This has become a lot more organised since last year. Once I've paid myself, put some aside for tax and put some in the rainy day fund, the rest is then distributed to 4 buckets:

  1. Pension
  2. Zopa
  3. Funding Circle
  4. Bricklane

2018 Goals & Results

£75,000 turnover 👍

Having got married in the middle of the year and then taking a month off I was unsure if this was going to be possible but amazingly as of today Freeagent is reporting my 12 month turnover as ~£110,000 🥳

Experiment with 4 day work week 👍

This actually worked really well. I only started doing it around the summer (I think) but it allowed to work on side projects and grow the business.

Sign with another client that is focussed on cryptocurrency 👎

Definitely a nice to have goal but it didn’t really come close to happening, I really didn’t put enough time and effort into getting this done.

Open source some of my libraries that I use everyday 👍

Really happy I was able to get back into doing open source. Over the year I released these projects:

100 paying Forecast customers 👎

Currently Forecast has 11 paying customers. I was super focussed on improving my freelance business that Forecast had to take a backseat.

Four Pints In Sponsorship 👍

Not a cash sponsor but I guess we technically hit this goal as Absolute Music provided us with audio equipment.

2019 Goals

  • £125,000 turnover.
  • Increase high quality incoming leads.
  • Improve on-boarding flow for new clients.
  • Release Quids.

Coinbase Swift SDK v1.2

Coinbase Swift SDK v1.2 has been released! A full list of changes can be found in the changelog but here are the main updates:

Token Swap Service

To remove the need to embed the oAuth secret key with the application, the SDK now requires a token swap service for the authorization flow. I have open sourced a token swap service that has a convenient Heroku deploy button so anyone can have a token swap service in a couple of clicks!

Fetch Auth Information

The API client has a new fuction that lets you query the user's auth information (docs).

public func fetchAuthInformation(_ completionHandler: @escaping (_ authInformation: AuthInformation?, _ errors: [Error]?) -> Void)

This also introduces a couple of new objects:

  • AuthInformation
  • AuthMetadata

I also updated the Auth object's scopes values to be Scope objects rather than strings.

Introducing xPal

In a previous post I talked about some methods for implementing macOS Mojave's Dark Mode. While we were adding Dark Mode support to Quids we found the process slow and error prone.

We thought; wouldn't it be cool if we could automagically generate our .xcassets asset catalog from our Sketch file?

xPal is a small tool that takes the artboards from a page in Sketch and generates an asset catalog for your Xcode project that contains all the colors named and grouped appropriately. Once your Sketch file has been prepared just drag and drop it onto the xPal window and it does the rest. Watch a demo here.

Download xPal here.

Implementing Dark Mode with macOS Mojave and Swift

With the latest macOS release, Apple introduced Dark Mode. Dark Mode changes the whole colour scheme of the OS to a darker, more subtle style. Not only does the OS change but so do the apps.

We recently added support for Dark Mode to Quids, our cryptocurrency Mac app. I was impressed with how easy Apple had made Dark Mode to implement and I expect to see a similar system come to iOS in the future.

If you have just used system colours such as NSColor.textColor, NSColor. selectedTextColor and NSColor.windowBackgroundColor, then your work is done!

However, you most likely have some custom colours. Here is an example of what our colour setup originally looked like:

internal extension NSColor
{
    internal struct Quids
    {
    	internal static let buttonBackground = NSColor(deviceRed: 250.0/255.0, green: 250.0/255.0, blue: 250.0/255.0, alpha: 1.0)
        // ... etc ...
    }
}

First step is to create a new Asset Catalog. Choose where you want to add the new file, right click, New File, Asset Catalog. Give it whatever name you want, I like to live on the edge and use Colors.xcassets.

Screenshot-2018-11-15-at-11.35.41

Next you need to add a colour set. Do this by either right clicking on the asset catalog’s left list view or by clicking the + button in the catalog’s bottom left and select “New Color Set”

Screenshot-2018-11-15-at-11.40.21

Now you’ll have something that looks like this:

Screenshot-2018-11-15-at-11.43.35

First things first, set the name. On the right side where it says “Name: Color” set this to whatever best describes your colour. I’m going to call mine ButtonBackground.

As it stands, this colour set is only setup as having no appearance, meaning that no matter what colour mode the user has, our ButtonBackground colour will always be the same.

On the right, select the “Any, Dark” appearance.

Screenshot-2018-11-15-at-12.01.58-1

You’ll see another colour swatch appear. Clicking a swatch will let you set the colour values:

Screenshot-2018-11-15-at-12.05.56

With the colours set, the last step is to update our code:

internal extension NSColor
{
    internal struct Quids
    {
    	internal static let buttonBackground = NSColor(named: "ButtonBackground")!
        // ... etc ...
    }
}

That’s it! We’re now all setup to use the colour in our app…

Using The Colour

If you’re using a standard control that takes an NSColor, for example NSTextField and NSWindow then all you need to do is set our new colour:

self.textField.textColor = NSColor.Quids.buttonBackground
self.window.backgroundColor = NSColor.Quids.buttonBackground

However, if you’re doing something a little more custom, like setting a CALayer’s background colour:

self.view.layer?.backgroundColor = NSColor.Quids.buttonBackground.cgColor

This won’t work. Never fear! There a few hooks that get called when the OS’s colour mode changes:

// NSViewController

override func updateViewConstraints() 
{
    super.updateViewConstraints()
    self.view.layer?.backgroundColor = NSColor.Quids.buttonBackground.cgColo
}

// NSView

override func updateLayer()
{
    super.updateLayer()
    self.layer?.backgroundColor = NSColor.Quids.buttonBackground.cgColor
}

override func layout()
{
    super.layout()
    self.layer?.backgroundColor = NSColor.Quids.buttonBackground.cgColor
}

override func updateConstraints()
{
    super.updateConstraints()
    self.layer?.backgroundColor = NSColor.Quids.buttonBackground.cgColor
}

Update

We've recently released xPal which automagically generates a Xcode color asset catalog from a Sketch file!

Xcode 10 Crash - device has no defaultDisplay

Upgrading to Xcode 10 has been pretty smooth apart from one issue. I'm unsure what causes it but the Simulator can constantly crash on startup with the error:

Device XXXX is available but has no defaultDisplay

Running this command fixed the crash loop for me:

sudo killall -9 com.apple.CoreSimulator.CoreSimulatorService

Thanks to this Stack Overflow post!

Quids Beta 2

We've just released Quids Beta 2 🎉

Read all about the new features here and register for beta here!