Swift - stride

func stride<T>(from start: T, to end: T, by stride: T.Stride) -> StrideTo<T> where T : Strideable

func stride<T>(from start: T, through end: T, by stride: T.Stride) -> StrideThrough<T> where T : Strideable

Found these pretty useful Swift functions the other day…

for countdown in stride(from: 3, through: 1, by: -1) 
{
    print("\(countdown)...")
}

// 3...
// 2...
// 1...

Swift - Deprecating a Renamed Function

To deprecate a renamed function that takes no arguments:

@available(*, deprecated, renamed: "reloadData")
func updateData() { }

func reloadData() { }

Or to deprecate a renamed function that takes arguments:

@available(*, deprecated, renamed: "reloadData(updatedUI:)")
func updateData() { }

func reloadData(updateUI: Bool) { }

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!

Crypto Icon API Service

Originally posted on Medium.


We’ve just released (and open sourced!) the web service we built for serving the cryptocurrency icons maintained by the Cryptocurrency Icons project.

The service was originally built for use in Quids for Mac to avoid bundling every icon with the client and having to make a new release everytime we supported a new currency. Instead, we use this service to dynamically accept the SVG source and render a PNG, using any of the included icon styles provided and at any size we need.

We have also released the Swift library we use in Quids to build the URLs.

The service is completely free to use but is provided “as is”. If you wish to guarantee uptime (like we do for Quids), I recommend deploying your own instance. The Github README has a Heroku button to make deploying your own instance of the service really simple.


https://cryptoicons.org

Bitrise + Bugsnag

Since Buddy Build was bought by Apple (congrats!) I’ve been keeping an eye out for a possible alternative. Not because Buddy Build has become rubbish since the acquisition (it’s still awesome) but because if it is shut down and absorbed into Apple (e.g. TestFlight) then I would have to spend a ton of time migrating client projects somewhere else.

So for new projects I have been using Bitrise. It is a lot more configurable than Buddy Build and definitely took a bit longer to get setup, but once I got my head around it, it became super powerful.

One out of the box “integration” that was missing was uploading dSYM files to Bugsnag. I’ve written a previous post about how I got this working with Buddy Build. Getting it to work with Bitrise is very similar:

Firstly you need to head over to the Workflow Editor. After your Xcode Archive & Export step, insert a Script step.

Under the config menu, set the working directory to $BITRISE_XCARCHIVE_PATH.

Then set the script content to:

#!/usr/bin/env bash
# fail if any commands fails
set -e
# debug log
set -x

ls **/*.dSYM/Contents/Resources/DWARF/* | while read line; do
    echo "Uploading $line"
    echo "Running: curl https://upload.bugsnag.com/ -F 'dsym=@$line'"
    curl https://upload.bugsnag.com/ -F "dsym=@$line"
done

Quids Beta

Beta--1-Art

We’ve just sent out our first beta build to our Product Hunt subscribers! Full blog post here.

If you want to try Quids just sign up here 😺

Observe Screen Locking in macOS

In Quids, similar to 1Password, we lock the app when your Mac locks.

There are two notifications sent via the DistributedNotificationCenter. One when the screen is locked and the other when it is unlocked. I couldn’t find any predefined variables so created this Notification.Name extension:

internal extension Notification.Name
{
    static let screenIsLocked = Notification.Name("com.apple.screenIsLocked")
    static let screenIsUnlocked = Notification.Name("com.apple.screenIsUnlocked")
}

Then all that is left to do is register an object as an observer:

DistributedNotificationCenter.default().addObserver(self, selector: #selector(...), name: Notification.Name.screenIsLocked, object: nil)

Send Money with the Coinbase Swift SDK

Photo by Thought Catalog / Unsplash

I recently added the ability to send money using the Coinbase Swift SDK that we’re building alongside Quids.

When going through the OAuth flow you need to add the CoinbaseAPIClient.Scope.createTransactions to your list of scopes:

let authScopes: [CoinbaseAPIClient.Scope] = [
    .readAccounts,
    .readTransactions,
    .createTransactions(sendLimit: 500.0, currencyCode: "USD", period: .day)
]

Then once you have the required permission you will need to build a SendMoney request and pass that to your CoinbaseAPIClient:

let request = CoinbaseAPIClient.SendMoney(to: ethAddress, amount: 2.5, currencyCode: "ETH")

coinbase.send(money: request, from: accountID, twoFactorCode: nil) { (transaction, errors) in
    // ...
}

You’ll notice this function can also take a 2FA code. If Coinbase returns a CoinbaseAPIClient.APIError.twoFactorRequired error, you should ask your user for a 2FA code and then re-call the send money function with the 2FA code.

Here is an example of how we’re doing this in Quids: Screen-Shot-2018-06-25-at-07.02.56

Coinbase Swift SDK

Over the weekend I released the Coinbase Swift SDK I’ve been building alongside Quids. It is still under heavy development so expect breaking changes!

Install

Carthage

github "reddavis/Coinbase"

Examples

Initialization

The framework gives you the flexibility of how you store the oAuth credentials. You will need to implement a class that conforms to the CoinbaseAPIClientAuthStore protocol. var isAuthenticated, var hasExpired and func delete() all have default implementations, so you will only need to implement var auth.

The library will handle the refreshing of tokens.

public protocol CoinbaseAPIClientAuthStore: class
{
    var auth: CoinbaseAPIClient.Auth? { get set }
    var isAuthenticated: Bool { get }
    var hasExpired: Bool { get }

    func delete()
}



public extension CoinbaseAPIClientAuthStore
{
    public var isAuthenticated: Bool {
        return self.auth != nil
    }

    public var hasExpired: Bool {
        guard let unwrappedAuth = self.auth else
        {
            return true
        }

        return unwrappedAuth.expiresAt < Date()
    }

    public func delete()
    {
        self.auth = nil
    }
}

Auth

Firstly you need to initialize the auth flow:

let scopes: [CoinbaseAPIClient.Scope] = [
    .readAccounts,
    .readAddresses,
    .createAddresses,
    .readTransactions,
    .readPaymentMethods,
    .readUser,
    .updateUser,
    .readUserEmailAddress
]

let url = self.coinbaseAPIClient.authorizeURL(scopes: scopes)
NSWorkspace.shared.open(url)

Then you need to get the oAuth token:

let redirectURL = URL(string: "quids://coinbase/auth")!

self.coinbaseAPIClient.authenticate(code: code, redirectURL: redirectURL) { (success, error) in
    self.authCompletionHandler?(success, error)
}

Requests

Only a few requests are currently supported, more will be added as we add features to Quids.

public func fetchAccounts(_ completionHandler: @escaping (_ accounts: [Account]?, _ errors: [Error]?) -> Void)
public func fetchTransactions(accountID: String, completionHandler: @escaping (_ transactions: [Transaction]?, _ errors: [Error]?) -> Void)
public func fetchCurrentUser(_ completionHandler: @escaping (_ user: User?, _ errors: [Error]?) -> Void)
public func updateCurrentUser(edits: UserEdits, completionHandler: @escaping (_ user: User?, _ errors: [Error]?) -> Void)
public func createAddress(accountID: String, completionHandler: @escaping (_ address: Address?, _ errors: [Error]?) -> Void)
public func fetchExchangeRates(baseCurrencyCode: String, completionHandler: @escaping (_ exchangeRate: ExchangeRate?, _ errors: [Error]?) -> Void)

Xcode 9.3 Simulator Freezes

For a few days I had an issue where every so often the iOS simulator would freeze when booting up. It would just display an activity indicator. Then I saw this Tweet and now all is fixed!

Weird Xcode install issues with unbootable simulators?

xcrun simctl erase all

resolved it for me

— Jason Kneen (@jasonkneen) April 30, 2018

Deprecator

Years ago at Togethera we built and open sourced our deprecation framework for iOS. It provided a way to remotely deprecate old versions of an app. Deprecator supported hard and soft deprecations.

Soft deprecations can be used to just let the user know that the latest version of the app has some new awesome feature and hard deprecations are used to force the user to upgrade. It’s not good practice, but it is useful to have as a backup incase of something going badly wrong.

The framework was left untouched and didn’t work with any new versions of Swift so I have now brought it back to life! You can find it on Github.

Segmented Control

I’ve just released SegmentedControl; a small UI control for iOS.

###

Install

In your Cartfile:

github "reddavis/SegmentedControl"

Example

let segmentedControl = SegmentedControl() 
segmentedControl.tintColor = UIColor.blue 
segmentedControl.addButton(title: "Button A") 
segmentedControl.addButton(title: "Button B")
segmentedControl.addButton(title: "Button C") 
segmentedControl.addTarget(self, action: #selector(self.segmentedControlValueDidChange(_:)), for: .valueChanged)
self.view.addSubview(segmentedControl)

Swift Framework - TableData v1

As mentioned in my Year in Review post from back in December, one of my aims of 2018 is to open source more code.

I’ve built a few private libraries over the years that I use in most of my projects. I figured releasing these would be a good place to start. The first one is the rather bland named; Table Data.

Table Data is a simple framework for building out UITableViews. I use it a lot when building preferences or settings screens.

Symple 1.1 - AutoPay

Last week we launched Symple 1.1! This release bring the ability to set your payments on autopilot with “AutoPay”. Just turn it on and choose the payment terms. Now when a partner sends an invoice you no longer need to manually manage paying them.

 

 

Telegram Bot Builder

TLDR; Introducing Telegram Bot Builder

I’ve built a few Telegram bots recently using Zapier and Chatfuel

Chatfuel used to work pretty well, though it always felt like Telegram was an after thought (just look at their homepage). Recently it stopped letting me create new bots. After asking support they said they had no ETA on fixing the issue. Two weeks later I gave up waiting and built T elegram Bot Builder; A more versatile Chatfuel. 

Bug Report Template

The author of the book Deep Work talks about The Principle of Least Resistance.

> The Principle of Least Resistance: In a business setting, without clear feedback on the impact of various behaviors to the bottom line, we will tend toward behaviors that are easiest in the moment.
— Cal Newport - Deep Work

Shitty internal bug reports are an example of this. Over the years I’ve seen so much time and money wasted from badly written bug reports. The amount of back and forth between developer and reporter can really rack up.

> The text is wrong colour
— CEO's bug report
> I can’t create X
— Developer Y bug report

 

How To Encourage Good Bug Reporting

Provide Real Examples

Choose a real bug report that someone or yourself filed and go through it, looking at it’s good and bad points.

Write Good Bug Reports Yourself

If you’re writing bug reports for others, write really well detailed ones. It won’t take long before they realise how useful it is.

Introduce a Template

Below is the bug report template I’ve used for the last few years. I usually customise it slightly depending on the project (iOS or macOS? Is there a dev server? etc). In the past I’ve also created a bookmarklet that automatically fills the text area of whatever tool we’re using.


## iOSVersion## BuildVersion## Device## Server## LoginDetails## Isitreproducible? Yes / Occasionally / One Time / No ## StepstoProduce/Reproduce1. 2. 3. ## ExpectedResults## ActualResults## Workarounds## OtherInformation

Documentation

I’ve worked with many companies over the years. The companies that work really well (remote or not) and can do a lot with a little (money and people) are the ones that document well.

By documentation, I mean asynchronous communication with your team:

  • Daily stand-ups. (the written type, not the “let’s disturb everyone to have a call” type)
  • Bug reports
  • Bug report updates
  • Labelling in Sketch files
  • Product roadmap
  • New feature ideas/research
  • Employee handbook
  • Shared password manager
  • Deployment logs
  • Commit messages
  • etc…

Writing documentation can be seen as a waste of time or money, however I have yet to see a instance where it has not made an improvement.

Next time someone interupts you by tapping you on the shoulder or @’ing you in Slack it might be worth making that knowledge more accessible.

Crypto Telegram Bot

All the Telegram crypto price tracker bots really suck, so I had a little play around with the bot API this evening and have managed to throw together something simple but useful (I think!)…

To use the bot either visit here or search for the user @CryptoPriceTrackerBot.

Then just type:

/[currency code] e.g. /xrp, /btc, /ltc

Thanks to KC for letting me use his face for the icon.

iOS Freelancer Diaries #4 - Year In Review

Blimey, what a year!

It’s been a long time since I last wrote a Freelance Diary entry (I know, I know. I said that last time too), so I figured I’d just write about the whole year.

Shameless self promotion - A lot of the numbers below are taken straight from Forecast.

Workload

The points below give a rough feel for my workload over the year. I feel things really started to change from September when I started booking in much larger projects and have managed to pretty much fill my schedule up until March 2018 🎉.

  • January - Mid Feb: Nothing
  • Feb - March: Semi booked
  • April: Fully booked
  • May - September: Semi booked
  • October - December: Fully booked

Clients

I’ve been very lucky this year and have worked with some great clients with projects ranging from an internal app for airport parking staff to the rather crazy world of cryptocurrency.

Over the year I’ve worked with 8 clients. The largest client contributed 35% to my turnover and the smallest; 3%.

Client A

  • 35% of turnover
  • Always paid on time

Client B

  • 24% of turnover
  • Paid on average 8 days late

Client C

  • 16% of turnover
  • Always paid on time

Client D

  • 9% of turnover
  • Paid on average 2 days late

Client E

  • 4% of turnover
  • Paid roughly 22 days late

Client F

  • 4% of turnover
  • Paid roughly 1 day late

Client G

  • 4% of turnover
  • Paid roughly 13 days late

Client H

  • 3% of turnover
  • Paid roughly 2 days late

Note: I realise the above doesn’t add up to 100%. I removed referral income from Gorilla and also a deposit for a project starting next year.

Notable Side Project

Forecast

Forecast is cash flow forecasting software for freelancers. It’s something I’ve personally wanted for a while so I teamed up with Nick to turn it into a reality.

Four Pints In

Towards the end of the year I started a Podcast called Four Pints In with two friends; Tom and Nick. In it’s simplest form; it’s 3 friends chatting over a beer or four. First episode was a bit nerve-racking but it’s been great fun to record and Tom has done a great job on the editing (Nick has also done a great job at turning up).

GFIB 7

Hector and I teamed up with a couple of friends who own a local gym called GFIB and put together our take on the “7 minute workout”.

Investments

It goes without saying, but I’m no expert…

Monzo

Monzo ran another crowdfunding and because I was involved in the first round I got to invest a % of my previous investment (£134.33).

Balance

Balance were actually a client of mine, but I also invested $1,000 in their crowdfunding. I think they have great potential to bring cryptocurrency to the mass market.

Pension

I had a private pension before but then paused contributions once I started freelancing. Once my runway improved I started £500/month contributions. I hope to raise this as my runway improves.

My pension is managed through St. James’s Place (I have a friend who works there). I have also heard good things about Nutmeg Pensions (though it has a £5k minimum deposit).

It’s also worth noting that since I have a limited company, the contributions are paid through that.

Stocks & Shares ISA

I also started a personal stocks & shares ISA with Nutmeg.

Financials

My aim at the start of the year was to turnover £60,000. This was my old salary so figured this was a good starting point.

By the end of the year turnover should have reached £65,000 🎉.

What’s crazy is that that just over half of that was created in the last 3 months.

Day Rate

I started freelancing with a day rate of £500. I’m a big believer in playing around with your day rate and over the year I have raised by rate by £25 every 2 clients (currently £600).

I also introduced a retainer rate at 20% discount.

Working For Equity

Though I have yet to officially do this, I get asked enough that I updated my contact page outlining my requirements.

The key points are:

  • Equity amount is based on the discount. For example, if I give a discount of £10,000, then in exchange I receive £10,000 in equity.
  • Provide any financial and business details I require
  • Pay all costs (e.g. legal)

The idea behind it came from the Sandwich Fund.

What Went Wrong

Too Much Work

As mentioned previously, I made just over half of my years turnover in 3 months. Yes, that sounds cool, but in reality it was too much. The summer had been relatively slow and I felt obliged to take on as much work as I could get my hands on. I’m now happy I did as it has given me a very solid foundation for 2018, but I don’t plan on doing that again, unless necessary.

Fixed Price Project

I’m generally totally against fixed price projects, it’s just not how building (good) software works. Unfortunately I didn’t listen to myself and took on a fixed price project. The scope was pretty well defined and payment was milestone based. The problem was that I hadn’t taken into account any dependancies that I needed from the client. These dependancies took a while to be ready and by that time I was due to start new projects, so I had to let the project go.

2018 Goals

Freelancing

  • £75,000 turnover
  • Experiment with 4 day work week
  • Sign with another client that is focussed on crytocurrency
  • Open source some of my libraries that I use everyday

Forecast

  • 100 paying customers

Four Pints In

Being able to land our first sponsorship would be awesome. We’d love to be able to outsource the editing of the episodes.

Framework not found X for architecture x86_64

This error happens when I try to run tests when using Carthage

This has happened to me a couple of times now and I keep forgetting how to fix it. So I thought I’d write it down here.

In your test target, add this to the Framework Search Paths…

$(PROJECT_DIR)/Carthage/Build/iOS

Or if you’re on macOS:

$(PROJECT_DIR)/Carthage/Build/Mac

🎉

Buddy Build + Bugsnag

I love Buddy Build, it’s simply a must have. But I’m personally not a huge fan of their crash reporter. For that, I use Bugsnag.

This is the Buddy Build post-build script I use to upload the dSYM to Bugsnag.

In the root of your project, just create a buddybuild_postbuild.sh file with the following:

Forecast - Clients

The more clients I work with, the harder it is to get a gist of the contributions each client makes to my yearly turnover. It can also be surprising when you find out a project that exhausts and drains you is only contributing 5% of your annual turnover. 

Having this kind of information is really powerful when organising your workload and deciding which clients to drop and which to keep.

We have just rolled out new Clients feature which helps you with these decisions. In Forecast there is a new “Clients” tab which simple displays a easily digestible summary of all your clients for the last 12 months along with your income from each client and the overall percentage. Forecast will also highlight any client that accounts for over 35% of your income (don’t put all your eggs in one basket!).

[Sign Up Now!](https://forecast.money/register)

Introducing Forecast

Since I started freelancing earlier this year, my most valuable metric has been how much runway I have left (or “how long before I need to get a real job”).

I use FreeAgent for all my finances. It’s a great tool, but it’s more about showing you your balance sheets and capital assets rather than the bigger picture.

So, I looked into forecasting software and found the likes of Float and Dryrun both of which look great… for large companies. I felt like I needed an accounting department just to get any value from them.

It’s for this reason that I’m very happy to announce my latest project: Forecast.

Forecast is a bullshit-free forecasting service for freelancers. It’s built on one key principle: no additional input from you is required.

To me, being a freelancer is all about the flexibility and the freedom to work on the things you enjoy. You should be too busy working on your projects or having fun outside of work, not babysitting another finance system. Once you’ve connected your FreeAgent account, that’s it! It just works.

Sign Up Now!

Scheduling Meetings With (Prospective) Clients

Almost 9 months into freelancing and I’m finding that the number of prospective clients is becoming a relatively steady flow. 🎉

Though some of my clients I have never actually spoken to (even during the “introduction”) the majority I have always had an initial chat with. This is usually a 30 minutes call on Hangouts.

However, this amazing situation brings a lot more of this:

> me - Can you do this time > them - no, can you do this time > me - no, can you do this time > ...
— old me

Without being able to see the other persons calendar, the only option is to choose a random time that I can do. This can lead the scenario above which is a waste of time and if you’re both stretched across multiple timezones it can take a while to come to a conclusion.

Solution

The other day I found a service called Calendly. The TLDR; Calendly gives you a link that you can share with the client. This link shows them all your available times in their time zone. All the client has to do is select which slot they want!

This then adds a calendar event. If you use Google Calendar, it can be setup to contain a Hangouts link, though Calendly does integrate with GoToMeeting.

Though my favourite feature is that you can limit the number of events per a day. I limit this to 1 so that my productivity isn’t destroyed by lots of calls.

This is what my availability looks like:

Invoicing + TransferWise

Taking a look at my clients in Freeagent I have about 50% that are UK based and the other 50% are based in the rest of Europe and the US.

When clients pay me, they send money to my GBP bank account. For my international clients this usually involves a charge either to them or me and sometimes a questionable exchange rate. This really sucks for me and my clients.

When Riot was around, we had attempted so many times to setup a US bank account but it was so much hassle and most of the time, the banks just said no. That was a long time ago and thankfully things have come a long way. I say things, but really I just mean one thing; TransferWise.

TransferWise has a product called Borderless Accounts. It’s amazing. Once you’ve signed up and verified you can just make yourself new EUR, GBP and USD bank accounts (I believe more are coming). Each account comes with all the necessary details to transfer money to.

With these borderless accounts there is no charge for the client to send me money. There is only a small fee for taking money out (price list).

Freeagent

How I’ve got this to work inside Freeagent is to add each borderless account as a bank account.

Now when I create a new invoice, I just select which accounts details I want to appear on the invoice. Magic! 

Day in the Life of a Freelance iOS Developer

I’ve always found these type of posts interesting to read, so I figured I’d write my own…

I have a fairly structured day. I find that keeping to a routine really helps me focus. I can feel lost without it.

 

5:45am

I like to wake up early. Mornings are definitely my most productive time.

My day starts off with breakfast, a shower and then I take the Poppy out for a walk. On average, the walk lasts around 45 minutes, though this depends on how many other dogs we meet on our way (Poppy likes to play with all of them).

Once we get home, I feed Poppy and make myself a coffee. My current brew method of choice is a Chemex.

7:30aM

This is when I start the first “block” of client work. 

For client projects I prefer to work in half day blocks. I respect my clients money and feel that if I’m jumping between projects/chores/phone calls and doing the odd couple of hours here and there, then I don’t feel they’re getting their moneys worth. I like to feel engrossed in a project which is why I also choose them carefully.

 

10:30am

Around 10:30am I usually take a break. My fiancé is currently back from university for the summer so I go and hang out with her and have my second breakfast of the day 🥐

12AM

When whatever I’m currently working on comes to a natural end, I break for Lunch. Either I’ll cook or reheat left overs from the evening before.

 

1pm

Once finished lunch, I’ll make a tea and continue the second block of client work.

 

4pm

I usually finish the day around 4. I’ll then reply to any emails and contact any potential leads for new projects. I also update my draft invoices. I don’t use any time tracking apps, I simply have draft invoices that I then add half or full day line items too.

How I Track My Time

Since I started freelancing back in January I’ve really trimmed down the number of services I’m using. I guess it felt really productive using so many.

How I work with my clients is always the same; invoice every second Friday and only work on a max of two clients per day (2 half day blocks).

So now I simply create draft invoices and then at the end of every day I add a new line item:

That’s it!

I have an event in my calendar that reminds me every Friday to send any invoices that need sending.

iOS Freelancer Diaries #3

It has been almost 3 months since my last freelance diary entry 😮. Here is a quick run through of how everything has been going…

Asking For Advice

Around the beginning of February I was feeling a bit deflated and started to have some doubts:

  • Is there something wrong with my portfolio?
  • Is my price too high/low?
  • Are my introduction emails terrible?
  • Why do all recruiters want me to work on site? Maybe remote isn’t going to work?

I knew getting my first client was going to be hard, but I was really hoping to have my first one by the start of February.

I decided to email a few UK based iOS freelancers and basically ask them for some advice on getting work. I have to say, the responses were awesome. They settled my doubts and also said that they would forward me any projects they couldn’t take on!

Side Projects

Projects

February 15th

I started my first project on February 15th. It was only a small 5 day project but it was a good start and helped extend my runway by about a month.

  • Project Source: Referral

 

February 28th

This was when things felt like they really started coming together. I was contacted by an awesome studio based in Northern Ireland who wanted ongoing help with various projects. This really helped in giving me a solid, predictable foundation for the future.

  • Project Source: Direct

 

March 24th

Towards the end of March I started my first “built from scratch” project. These are the kind of projects I love to work on. I’m looking forward to sharing this soon.

  • Project Source: Referral (from one of the freelancers mentioned above, thanks!)
  • Estimated time: 3 weeks

 

April 10th

A small MVP project.

Financials

My target turnover for the year is £60,000, meaning I need to hit a minimum of £5,000 a month. So far my turnover is £11,654 meaning I’m currently short by £8,346. Since I didn’t have a client from the start, this was always going to be the case so I shouldn’t be too hard on myself.

The iOS Simulator Scroller

TLDR; GIVE IT TO ME NOW!

Just over a week ago I decided to play around with Accessibility on macOS. I’ve always wanted the iOS Simulator to scroll when I scrolled with my mouse so figured this would be a good project to get started on.

Later on that day I had this:

Playing around with the accessibility framework. Put together an app that lets me use my mouse scroll in the iOS simulator 🎉 pic.twitter.com/qS4XteB5fN

— Red Davis (@reddavis) March 13, 2017

A few people asked for me to release it and I figured why not? Would also give me a chance to try out Paddle which we have been thinking of using for Quids

You can try out the iOS Simulator Scroller by visiting here.

Podcasts I Listen To

I listen to a lot of Podcasts. I actually listen to them to help me fall asleep, I am not sure why, but I can’t fall asleep when everything is quiet.

A lot of people (and by a lot, I mean like 4) have asked me what Podcasts I listen to, so I thought I’d list them here:

 

Hello Internet

Presented by CGP Grey and Dr. Brady Haran.

 

Accidental Tech Podcast

A tech podcast we accidentally created while trying to do a car show. Featuring Marco ArmentCasey Liss, and John Siracusa.

 

Supertop Podcast

Behind the scenes at Supertop as Pádraig and Oisín reflect on their work as indie developers.

 

Back to Work

Back to Work is an award winning talk show with Merlin Mann and Dan Benjamin discussing productivity, communication, work, barriers, constraints, tools, and more. Hosted by Merlin Mann and Dan Benjamin.

 

The Checked Shirt

Jason and Ben talk about freelancing, apps, and tech news with a healthy skew towards Apple.

 

Core Intuition

A podcast about indie software development for the Mac, iOS and other Apple technologies.

 

Cortex

CGP Grey and Myke Hurley are both independent content creators. Each episode, they discuss the methods and tools they employ to be productive and creative.

 

Debug

Debug is a conversational interview show about developing software and services, primarily for iPhone, iPad, Mac, and gaming. Hosted by Guy English and Rene Ritchie, it’s all the great talk you get at the bar after the conference, wrapped up in convenient podcast form. Pull up a chair, hit play, join us.

 

Developer Tea

A podcast for developers designed to fit inside your tea break.

 

Fatal Error

Fatal Error is a podcast about iOS development, hosted by  Soroush Khanlou and Chris Dzombak. We discuss topics at the cutting edge of iOS software architecture, Swift, and best practices.

 

The Pen Addict

The Pen Addict is a weekly fix for all things stationery. Pens, pencils, paper, ink – you name it, and Brad Dowdy and Myke Hurley are into it. Join as they geek out over the analog tools they love so dearly.

 

Reconcilable Differences

John Siracusa and Merlin Mann try to figure out exactly how they got this way.

 

Release Notes

Release Notes is a weekly podcast about the business of Mac and iOS indie software development. We discuss inspiration, design, trends, and tools — everything but the code.

Each week, we cover topics for the new or curious independent developer looking to make his or her way in the iOS and Mac ecosystem. Tips and tricks, success stories as well as failures. The show is hosted by Charles Perry, owner of Metakite Software, and Joe Cieplinski, Creative Director of Bombing Brain Interactive.

 

Startups For the Rest of Us

Welcome to Startups for the Rest of Us, the podcast that helps developers, designers and entrepreneurs be awesome at launching software products. Whether you’ve built your first product or are just thinking about it.

 

The Talk Show

The director’s commentary track for Daring Fireball.

 

Under the Radar

From development and design to marketing and support, Under the Radar is all about independent app development. It’s never longer than 30 minutes.

 

Ask a Freelancer

A podcast series where experienced freelancers answer questions about freelancing.

 

iOS Freelancer Diaries #2 - Prospective Clients

Today marks three week since I started freelancing. It’s crazy how fast it’s gone by. These last three weeks have been all about one thing; sales!

If there’s one thing I’ve learnt, it’s to never stop selling. You might think a project is in the bag, but until the deposit has been paid it is not guaranteed (even then you never truly know). Already have a two month project? Then you should be aiming to book a project for after.

Stats

  • Number of deals: 15
  • Deals lost: 5
  • Proposals written: 4
  • Estimated value of all proposals: £71,500 - £91,500

Organising Deals

To help me keep track of all my deals I am using a website called Pipedrive. This is what my Pipedrive dashboard looks like:

Pipedrive uses a similar layout to a Kanban board. You can add, remove or change any of the columns to suit your needs and add or move cards (“deals”) around the board. It also has a load of other features like: bcc’n emails and “activities”, but I like to just keep it simple.

Contact Made

Once there has been two way communication between the prospective client and I, I will add a deal to the Contact Made column. During this time we would have spoken about the project so that I can get an understanding of the main concept. It is also very important to check that they are aware of costs, time and my payment terms. If app development is new to the client I usually highlight a small and large portfolio piece of mine and explain how long they roughly took to complete.

Proposal In Progress

I’ve uploaded my proposal template on Github for anyone to use. It’s pretty straight forward. I start off with describing the audience of the project. Working on Togethera taught me that building for your audience is crucial. Then I move onto an overview of the app; this is basically a user story of the main flow of the app.

Next it’s the technical overview. If I’m also building the web API I will layout some rough model designs. These are not final but it’s a very useful exercise to get an overview of how to organise the data. For the app I write a overview of all the potential screens. If there are already designs, then I put an image of each screen into the proposal and give an overview of it’s functionality. Throughout the proposal I also highlight any questions, recommendations or ideas that I have.

Depending on the size of the app there could be a couple of “main features”. These are the focus of the app. Is it a weather app? Then viewing the weather forecast is the “main feature”. For the main features, I just go into more depth.

If the screens haven’t been designed yet then I’ll use POP to put together a mockup. I write about doing this in a previous post.

The majority of projects will use third party services. Whether that’s S3 for file storage or Intercom for customer support, I write them all down. Sometimes they won’t have their own SDK’s so I might need to write a small (or maybe large!) library for the API.

Below this I highlight any unknowns that I have. Having too many unknowns makes it hard to give a semi-accurate estimate.

Last but not least, is the estimate. This will either be a single value or a range.

Proposal Made

Once the proposal has been sent, I’ll move the deal into the Proposal Made column. From here it will either go two ways: they reply and the deal is moved into Negotiations Started or I don’t hear anything back…

Don’t panic, it’s cool, they don’t hate you.

So far, pretty much every time the client has been refining or rethinking the idea, trimming down on some feature or just awaiting input from their colleagues. After about a week I usually send a follow up email to check if they had a chance to look at the proposal and if they have any questions.

Pact Coffee ASAP Button

I’m a long time subscriber to Pact Coffee (referral link), it’s awesome and very reasonably priced.

It has a great feature where you estimate the number of coffees you drink per week so that they can send you your next bag just in time before your previous bag runs out.

Though, some weeks can be tougher than others and you suddenly find yourself quickly running out! 😵

No problem, you can just login to their website and click a button that says “Ship today”, but by the time you have made you coffee, ate a biscuit, read an email and got back to your desk, you forget 😰 At least, this is what happens to me.

This week has been all about writing proposals, so I thought I’d take a break and write a simple one button iOS app that would change my order to “Ship today”.

Pact do not have an API so I figured I’d have to just scrape their site. I threw together a small Rails app that would act as the API for the client. At first, I tried to use Mechanize though I then realised the Pact site is written in React (at least I think). Mechanize doesn’t work with Javascript. To get around this I ended up using Capybara and PhantomJS. I built two endpoints: “auth” and “ship today”.

The iOS app is super simple. It just implements the two API endpoints, stores the email and password in the keychain and I threw 1Password in there because every app should have 1Password integration.

Since I’ve built this hacked together API, it would be great to connect some sort of IOT button to it. 

iOS Freelancer Diaries Diaries #1

On the 1st January 2017 I am going freelance 🎉. It has been about 3 years since I last freelanced.

I’ve decided to try and keep a diary to share my experiences, lessons and the highs and lows. This first post is focussed on getting started, what do I need? It will be localised to the UK, but it’s likely your country has a similar setup.

I’ve also created a repo on Github with useful freelancing resources.


Getting Started

So after much thought, I decided to go freelance. Before that official “I’m freelance!” date arrives, there are few things I needed to take care of:

 

Savings

It’s very possible that thing’s will start slowly, especially, if like me, you are starting at the start of January. 

I don’t want to force myself into having to take crappy work. To give myself some freedom, I saved around £9K.

 

Registering a LTD Company

There are bunch of reasons to have a LTD company, rather than being a Sole Trader.

Registering one is really easy. The Gov UK website has lots of information about registering. You can also use a service like 1st Formations, that will register the company for you plus other things like VAT.

 

VAT Registration

You will need to register for VAT if (dated: 29/12/2016):

  • Your VAT taxable turnover is more than £83,000 (the ‘threshold’) in a 12 month period
  • You receive goods in the UK from the EU worth more than £83,000
  • You expect to go over the threshold in a single 30 day period

The first rule only really affects me. However “VAT taxable turnover” is quite vague. I’m currently waiting to hear from my accountant about what exactly is “VAT taxable turnover”. For example, if all my work is from the US, I would presume that it wasn’t “VAT taxable turnover”. ¯_(ツ)_/¯ TLDR: if any doubt ask a professional.

 

Business Bank Account

In the UK, there is no legal requirement to have a business bank account for a LTD company. However, I find it just cleaner to keep all business activity separate from my personal account. Plus my poor accountant will have a headache trying to work out what transactions are business and what transactions are me buying dishwasher salt.

In the past I have had my business bank account with HSBC. They were perfectly good, though one issue I had was that whenever I wanted to sync Freeagent with the account, I had to input a key code. This would mean that the account would rely on me to keep everything in sync. I’ve decided to go with Santander this time as a key code is not required to sync with Freeagent. 

 

Accountant

I would really recommend getting an accountant. They will save you money, time and stress. Just do it.

I really like Freeagent so my main requirement is that the accountants can use Freeagent.

Freeagent has a webpage showing some of the accountants that use it’s software.

I have chosen Gorilla Accounting. They seem heavily focused on freelancers and have a reasonable flat rate of £85/month. I’ve only just registered with them but will update this post if I’m unhappy and choose another company.

 

Business Insurance

Insurance is something you don’t think you need it until you need it, then it’s too late. Same as the accountant, just get it.

I’m going with Jack. Like the accountant, it’s focussed on freelancers and the website is really nicely done. Plus, you get some cool free stuff when you sign up.

 

All Set!

That’s it! All pretty simple. If you’re interested in going freelance or just have any questions, feel free to email me or leave a comment below!

Automatically Controlling a Dehumidifier with a Nest

On the desk I have a Nest. For those that don’t know, the Nest is a “smart” thermostat. Along with being able to do Thermostat things smartly, it can also detect humidity.

Wouldn’t it be cool if, when the Nest detects that the humidity has risen past a certain threshold, the dehumidifier is turned on and is turned off again when it goes below the threshold? Of course it would be…

Graphs are awesome too, so let’s throw a graph in there, showing outside temperature, inside temperature and humidity.

To get started, you’re going to need a few things:

IFTTT Setup

I created two recipes; one to turn on the dehumidifer and one to…well…turn off the dehumidifer.

The recipes are simple. They use the Maker channel and the Wemo switch channel.

The Maker channel basically exposes a URL that we can trigger by sending POST or GET requests too.

Installing Recipes

Off Recipe

  • Visit here
  • Set Event Name to low_humidity
  • Select your Dehumidifier’s Wemo Switch
  • Click Add

On Recipe

  • Visit here
  • Set Event Name to high_humidity
  • Select your Dehumidifier’s Wemo Switch
  • Click Add

Maker URL’s

You need to get your Maker URL. You can get this by:

  • Visiting here
  • Click “How to Trigger Events”

Now copy that URL. It should look something like:

https://maker.ifttt.com/trigger/{event}/with/key/XXXXXX

Next, we need to create two URL’s. One with low_humidity event and one with high_humidity. You should now have:

https://maker.ifttt.com/trigger/low_humidity/with/key/XXXXXX https://maker.ifttt.com/trigger/high_humidity/with/key/XXXXXX

Deploy To Heroku

  • Go to this Github repo
  • Click the magic Deploy To Heroku button

Almost there, just two more things. Heroku should now ask you for some environment variables.

  • Nest email address
  • Nest password
  • IFTTT turn on URL (high_humidity event)
  • IFTTT turn off URL (low_humidity event)
  • Humidity threshold
  • Forecast IO API Key

Last but not least you need to setup the Heroku Scheduler.

When viewing your application in Heroku, there should be a “Heroku Scheduler” addon. Click it. Add a job to run rake collect_reading every 10 minutes. It should look something like this.


Result!

You should now have a webpage.

To test everything out, you can go to your application settings in Heroku and change the HUMIDITY_THRESHOLD config variable to something really low. When the scheduler next runs your dehumidifer should turn on!

Now if I could only automate emptying the dehumidifer…