Skip to content

Instantly share code, notes, and snippets.

Tim Shadel timshadel

View GitHub Profile
timshadel / Matchers.swift
Created Feb 16, 2019
XCTest custom matchers
View Matchers.swift
// XCTestCase+Matchers.swift
// greatwork
// Created by Tim on 4/14/17.
// Copyright © 2017 OC Tanner Company, Inc. All rights reserved.
import Foundation
import XCTest
import Marshal
timshadel /
Last active Aug 18, 2017
iOS automatic version script
# Version: $Major.$Minor.$Commit
# How it works:
# 1. To roll minor number, tag each App Store release with a message.
# 2. To roll major number, create an additional tag on the last App Store
# release (e.g. "2.17.9") with new major number (e.g. "3").
# 3. `Release` builds require a clean working directory.
timshadel / SafeArray.swift
Created May 15, 2017
A start of thread safe access to an array.
View SafeArray.swift
struct SafeArray<Element> {
private let multiReaderQueue: DispatchQueue
private var array = [Element]()
init() {
multiReaderQueue = DispatchQueue(label: "safeArray.internal", attributes: .concurrent)
var count: Int { return read { self.array.count } }
timshadel / toc.rb
Created Jan 28, 2017
Generate TOC for Github markdown docs
View toc.rb
#!/usr/bin/env ruby
# Generate a correct table of contents for Github markdown documents
# See
doc = IO.readlines(ARGV[0])
lines = { |l| l.start_with? "#" }.map do |l|
indent = l.chomp.gsub(/^# .*/, '* ').gsub(/^## .*/, ' * ').gsub(/^### .*/, ' * ')
link = l.gsub(/[^a-zA-Z\- ]/u,'').strip().downcase.gsub(' ','-')
indent + l.chomp.gsub(/^([\# ]*)(.*)$/, '[\2]') + "(##{link})"
timshadel /
Last active Jan 13, 2017
Draft of Swift Evolution Proposal for Case Blocks

Enum Case Blocks

  • Proposal: SE-XXXX
  • Authors: Tim Shadel
  • Review Manager: TBD
  • Status: TBD


Add an optional syntax to declare all code related to a single case in one spot. For complex enums, this makes it easier to ensure that all the pieces mesh coherently across that one case, and to review all logic associated with a single case. This syntax is frequently more verbose in order to achieve a more coherent code structure, so its use will be most valuable in complex enums.

timshadel / APNG.swift
Created Aug 1, 2016
Programmatically create APNG files
View APNG.swift
// By Heber Sheffield
public class func save(animatedImageSequence images: Array<CGImage>, withFrameDelay delay: CGFloat, numberOfLoops: Int, to url: URL) {
let fileProperties = [kCGImagePropertyPNGDictionary as String: [kCGImagePropertyAPNGLoopCount as String: numberOfLoops]]
let frameProperties = [kCGImagePropertyPNGDictionary as String: [kCGImagePropertyAPNGDelayTime as String: delay]]
guard let destination = CGImageDestinationCreateWithURL(url, kUTTypePNG, images.count, nil) else { fatalError("couldn't create image destination for url: \(url)") }
CGImageDestinationSetProperties(destination, fileProperties)
for image in images {
CGImageDestinationAddImage(destination, image, frameProperties)
View Instead of Guard Let
infix operator !! { associativity left precedence 160 }
@inline(__always) public func !!<T>(value: T?, @autoclosure die: () -> Void) -> T {
guard let value = value else {
return value
let test: String? = nil
timshadel / 0_reuse_code.js
Last active Aug 29, 2015
Here are some things you can do with Gists in GistBox.
View 0_reuse_code.js
// Use Gists to store code you would like to remember later on
console.log(window); // log the "window" object to the console
timshadel / EmptyPodForWatchExtension.h
Last active Aug 29, 2015
Empty Pod For Watch Extension
View EmptyPodForWatchExtension.h
* If your watch extension doesn't need any of it's own exclusive pods,
* it won't have its header search path set to see any of the dependencies
* of embedded frameworks it relies on. This fixes that without duplication.
@interface EmptyPodForWatchExtension
timshadel /
Last active Aug 25, 2019
A Facebook post in HTML and hyper+json.

Compare & Contrast

HTML, Hyper+JSON, and Data as JSON

OK. Everyone's got LOTS of questions and emotions around how to use hyper. I want to answer them, but first I want to walk you through a comparison exercise.

  1. Take a look at the screenshot below of a typical Facebook post.

    Think about the ways you could navigate or interact with this FB post, based only on what you see. Any kind of interaction you take either moves the view to another object, or it alters the data of this object.

You can’t perform that action at this time.