Skip to content

Instantly share code, notes, and snippets.

@khanlou
khanlou / CanCan.swift
Created Feb 14, 2021
A version of Ruby's cancan for Swift.
View CanCan.swift
import Foundation
struct CanCan<Identity, Action: Equatable> {
var registry: [(String, (Identity, Any) -> [Action])] = []
mutating func register<T>(_ type: T.Type, _ block: @escaping (Identity, T) -> [Action]) {
self.registry.append((String(describing: type), { (identity: Identity, object: Any) -> [Action] in
guard let casted = object as? T else {
return []
View Git-Hours.md

This is a quick way to approximate how many person-hours have put into a git repo.

git log --pretty=format:"%ae %ad" --date=format:'%Y-%m-%d %H' | uniq | wc -l

The --pretty=format gives you the author email and commit date, and the date is formatted to just include the year, month, day and hour, like so: 2020-12-22 16. You can add a grep before or after the unique to filter out by author. wc -l tells you the number of lines, which are uniqued, meaning if you had two commits in the same hour, those are filtered out.

View IndexedForEach.swift
//
// IndexedForEach.swift
//
//
// Created by Soroush Khanlou on 1/21/20.
//
//
import Foundation
import SwiftUI
View GregorianDate.swift
//
// GregorianDate.swift
//
//
// Created by Soroush Khanlou on 12/22/20.
//
import Foundation
public struct GregorianDate: Equatable, Hashable, Comparable, Codable, CustomStringConvertible {
View SumWithBlock.md

Sum With Block

Introduction

While Swift’s Sequence models brings a lot of niceties that we didn’t have access to in Objective-C, like map and filter, there are other useful operations on sequences that the standard library doesn’t support yet. One operation that is currently missing is summing numeric values on elements in a sequence.

View SumWithBlock.swift
extension Sequence {
func sum<T>(_ transform: (Element) -> T) -> T where T: AdditiveArithmetic {
var sum = T.zero
for element in self {
sum += transform(element)
}
return sum
}
}
@khanlou
khanlou / YouDeserveNiceErrors.swift
Last active Oct 18, 2020
Nicer descriptions for DecodingErrors
View YouDeserveNiceErrors.swift
extension DecodingError.Context {
var pathDescription: String {
pathDescription(for: codingPath)
}
func path(including final: CodingKey) -> String {
pathDescription(for: codingPath + [final])
}
private func pathDescription(for path: [CodingKey]) -> String {
View A-Usage.md

This is designed to look like sheet(item:content:):

func sheet<Item, Content>(item: Binding<Item?>, content: @escaping (Item) -> Content) -> some View

But for pushing views instead of presenting them as sheets.

To use it, create a @State variable for your selected item:

@State var selectedPerson: Person?
View Geohelpers.swift
import Foundation
import MapKit
extension MKMapPoint {
static var nyc: MKMapPoint {
return MKMapPoint(.nyc)
}
}
extension MKMapRect {
View Statistics.swift
struct Statistics {
private(set) var count: Double = 0
private(set) var sum: Double = 0
private(set) var sumOfSquares: Double = 0
var average: Double {
sum / count
}