Skip to content

Instantly share code, notes, and snippets.

View jakehawken's full-sized avatar
🆒

Jake Hawken jakehawken

🆒
View GitHub Profile
@jakehawken
jakehawken / ComposableCollectionView.swift
Last active September 7, 2023 01:10
Eschew delegation. Embrace composition.
// ComposableCollectionView.swift
// Created by Jake Hawken
import UIKit
/// Represents the data for a section of a table view or collection view.
///
/// If different sections have different element types, it's recommended to
/// create an enum with a case for each element type, and use that enum as
/// the Item type of the ComposableCollectionView.
@jakehawken
jakehawken / ComposableTableView.swift
Last active September 7, 2023 00:57
Eschew delegation. Embrace composition.
// ComposableTableView.swift
// Created by Jake Hawken
import UIKit
class ComposableTableView<Item, SectionTypeID: Hashable>: UIView {
typealias Section = SectionViewModel<Item, SectionTypeID>
private let tableView: UITableView = UITableView()

Keybase proof

I hereby claim:

  • I am jakehawken on github.
  • I am jakehawken (https://keybase.io/jakehawken) on keybase.
  • I have a public key ASC9G7boDUOq6QZmANcSV92WoFNEs6TyLDgleW99D33cGgo

To claim this, I am signing this object:

@jakehawken
jakehawken / ShadowBox.swift
Last active August 24, 2023 21:10
Shadows or rounded corners. To that I say ¿Porque no los dos?
extension UIView {
/// Adds the subview to a container with shadows on it and returns the container.
/// Primary use case is for a subview that clips to its bounds, and therefore can't
/// have a shadow on its own `layer`. The shadow will match the corner radius of
/// the contained view.
static func shadowContainerFor(
_ subview: UIView,
shadowColor: UIColor? = .darkGray,
shadowRadius: CGFloat = 2,
@jakehawken
jakehawken / DiskBacked.swift
Last active July 12, 2023 20:27
@DiskBacked - Easy computed properties backed by UserDefaults.
/// This propety wrapper generates a variable that is backed by UserDefaults.
/// This can be used with any Codable type, and saves the item to disk as Data.
/// At initialization, you supply the key at which the the variable will be
/// saved, and the instance of UserDefaults in which to save it.
///
/// Like any other variable, it can be made get-only using `private(set)`, to
/// allow for better encapsulation, if so desired.
///
/// Example usage:
/// ```
@jakehawken
jakehawken / NonNil.swift
Last active July 12, 2023 20:27
@nonnil - crash with purpose!
/// The NonNil property wrapper allows you to supply an error message at the declaration of a
/// property, and then otherwise access it like it's non-nil in your code. Any access before it's
/// set will still result in a crash the way explicity unwrapping would, but with the added benefi
/// of there being an informative crash message. Intended to be a conscientious and thoughtful
/// replacement for the `!` operator.
///
/// I hate explicitly unwrapped optionals in Swift (or as I call them, "explosive optionals"). They
/// sidestep the responsibility of the dev to handle nil values, and they crash the app without
/// any specific information to send to a logger or debugger. If the nil state isn't a valid state,
/// and it necessitates a crash, I still want there to be a message handed off to the logger/debugger
@jakehawken
jakehawken / TableViewComposer.swift
Created November 25, 2022 23:59
A type for managing and encapsulating UITableViews with a more declarative interface, and without leaky encapsulation
// TableViewComposer.swift
// Created by Jacob Hawken on 5/28/22.
import UIKit
class TableViewComposer<T, E:Error>: NSObject {
struct Section {
let title: String?
let items: [T]
@jakehawken
jakehawken / WordleWords.swift
Created June 14, 2022 18:33
A Swift Set of all the words used in the Wordle. Credit for the source of this goes to @tabatkins https://github.com/tabatkins/wordle-list/blob/main/words
let words: Set<String> = [
"aahed",
"aalii",
"aargh",
"aarti",
"abaca",
"abaci",
"aback",
"abacs",
"abaft",
extension Array {
func scan(forEachNeighbors action: (Element, Element) -> Void) {
guard count >= 2 else {
return
}
var indexA = 0
var indexB = 1
while indexB <= count - 1 {
// InsetTextField.swift
// Created by Jacob Hawken on 4/2/22.
import UIKit
class InsetTextField: UITextField {
var leftInset: CGFloat = 8 { didSet { setNeedsLayout() } }
var rightInset: CGFloat = 8 { didSet { setNeedsLayout() } }
var topInset: CGFloat = 8 { didSet { setNeedsLayout() } }