Skip to content

Instantly share code, notes, and snippets.

View JohnSundell's full-sized avatar

John Sundell JohnSundell

View GitHub Profile
@JohnSundell
JohnSundell / ContentViewWithCollapsableHeader.swift
Last active April 25, 2024 06:41
A content view which renders a collapsable header that adapts to the current scroll position. Based on OffsetObservingScrollView from https://swiftbysundell.com/articles/observing-swiftui-scrollview-content-offset.
import SwiftUI
/// View that observes its position within a given coordinate space,
/// and assigns that position to the specified Binding.
struct PositionObservingView<Content: View>: View {
var coordinateSpace: CoordinateSpace
@Binding var position: CGPoint
@ViewBuilder var content: () -> Content
var body: some View {
@JohnSundell
JohnSundell / ErrorTypeExample.swift
Created March 28, 2017 18:00
Example on how you can name your own types using the same name as a standard libary type
extension Command {
enum Error: Swift.Error {
case missing
case invalid(String)
}
}
@JohnSundell
JohnSundell / AnyOf.swift
Created August 21, 2017 21:23
A way to easily compare a given value against an array of candidates
import Foundation
struct EquatableValueSequence<T: Equatable> {
static func ==(lhs: EquatableValueSequence<T>, rhs: T) -> Bool {
return lhs.values.contains(rhs)
}
static func ==(lhs: T, rhs: EquatableValueSequence<T>) -> Bool {
return rhs == lhs
}
@JohnSundell
JohnSundell / SwiftUITimers.swift
Last active March 23, 2023 12:02
Timer-based example used during my Advanced SwiftUI workshop.
import SwiftUI
// Model + controller:
struct NamedTimer: Identifiable, Equatable {
let id = UUID()
var name: String
var seconds = 0
}
@JohnSundell
JohnSundell / ListViewModel.swift
Last active February 17, 2023 15:27
Example view model class used during my Advanced SwiftUI workshop
import SwiftUI
struct Item: Equatable, Identifiable {
let id = UUID()
var title: String
var isFavorite = false
}
@MainActor class ListViewModel: ObservableObject {
@Published private(set) var items: [Item] = []
@JohnSundell
JohnSundell / StarPlane.swift
Created July 8, 2020 22:41
A simple game written in SwiftUI. Note that this is just a fun little hack, the code is not meant to be taken seriously, and only works on iPhones in portrait mode.
// A fun little game written in SwiftUI
// Copyright (c) John Sundell 2020, MIT license.
// This is a hacky implementation written just for fun.
// It's only verified to work on iPhones in portrait mode.
import SwiftUI
final class GameController: ObservableObject {
@Published var plane = GameObject.plane()
@Published private(set) var clouds = [GameObject]()
@JohnSundell
JohnSundell / CrossPlatformImages.swift
Last active November 22, 2022 06:29
An easy way to make code that uses UIImage cross-platform between iOS/tvOS & macOS
// Either put this in a separate file that you only include in your macOS target
// or wrap the code in #if os(macOS) / #endif
import Cocoa
// Step 1: Typealias UIImage to NSImage
typealias UIImage = NSImage
// Step 2: You might want to add these APIs that UIImage has but NSImage doesn't.
extension NSImage {
@JohnSundell
JohnSundell / simrecord
Created March 16, 2018 21:05
🎥 Script that lets you start a video recording from the iOS simulator with one command
#!/bin/bash
ITERATION=1
EXTENSION="mp4"
FILENAME="$HOME/Desktop/Simulator Recording.$EXTENSION"
while [ -e "$FILENAME" ]
do
ITERATION=$((ITERATION+1))
FILENAME="$HOME/Desktop/Simulator Recording $ITERATION.$EXTENSION"
@JohnSundell
JohnSundell / Autoclosure.swift
Created January 19, 2017 15:00
Simple Dictionary extension to avoid the if let-dance when retrieving values
extension Dictionary {
mutating func value(for key: Key, orAdd closure: @autoclosure () -> Value) -> Value {
if let value = self[key] {
return value
}
let value = closure()
self[key] = value
return value
}
@JohnSundell
JohnSundell / Optional+Require.swift
Created November 27, 2017 18:05
Extension that lets you require an optional to be non-nil, or throw an error (which is customizable)
extension Optional {
struct RequireError: Error, CustomStringConvertible {
var description: String {
return "Required optional value was nil"
}
}
func require(orThrow errorClosure: @autoclosure () -> Error = RequireError()) throws -> Wrapped {
switch self {
case .some(let value):