Skip to content

Instantly share code, notes, and snippets.

View Joony's full-sized avatar
🏠
Working from home

Jonathan McAllister Joony

🏠
Working from home
  • Copenhagen, Denmark
View GitHub Profile
@Joony
Joony / BorderBinarySearch.swift
Last active November 29, 2023 10:23
Find the border between a repeating value and any other value. Both left and right versions.
/**
Find the border between a repeating value and anything else.
- Parameters:
- key: The repeating value
- range: The range of indexes to search for the border within.
- f: A function to generate values.
- Returns: The last index of key.
*/
func borderBinarySearchFLeft<T: Comparable>(lowerKey: T? = nil, range: Range<Int>, f: (Int) -> (T?)) -> Int? {
var lBound = range.lowerBound
@Joony
Joony / MLModel+Download
Last active April 13, 2023 11:46
Download and compile an MLModel.
import CoreML
extension MLModel {
/**
Use the model: `let model = try MLModel(contentsOf: permanentURL)`
*/
func download(url: URL) async throws -> URL {
let request = URLRequest(url: url)
@Joony
Joony / LocalGravity.swift
Last active March 30, 2023 13:31
Calculate local gravity for a given latitude and elevation
func localGravity(latitude: Double, elevation: Double) -> Double {
let a: Double = 0.0053024
let b: Double = 0.0000058
let l = latitude * .pi / 180
let sinl: Double = sin(l)
let sinl2: Double = sinl * sinl
let sin2l: Double = sin(l * 2)
let sin2l2: Double = sin2l * sin2l
let t: Double = 1 / 1000000
@Joony
Joony / ScreenRecoderModel.swift
Created March 22, 2023 10:26
A SwiftUI model for recording the screen.
import ReplayKit
class ScreenRecorderModel {
private let recorder = RPScreenRecorder.shared()
var isAvailable: Bool { recorder.isAvailable }
func start(handler: ((Error?) -> Void)? = nil) {
recorder.startRecording(handler: handler)
}
@Joony
Joony / Publisher+RetryInterval
Created January 3, 2023 08:38
A Combine publisher where you can specify a time interval between retries.
import Combine
extension Publisher {
func retryWithDelay<T, E>(retries: Int, interval: DispatchQueue.SchedulerTimeType.Stride) -> Publishers.Catch<Self, AnyPublisher<T, E>> where T == Self.Output, E == Self.Failure {
self.catch { error -> AnyPublisher<T, E> in
Publishers.Delay(
upstream: self,
interval: interval,
tolerance: 1,
scheduler: DispatchQueue.global()
@Joony
Joony / ViewSize.swift
Created November 11, 2022 12:31
SwiftUI - Have a child view report its size to a parent.
import SwiftUI
struct ViewSize: ViewModifier {
struct ViewSizePreferenceKey: PreferenceKey {
typealias Value = CGSize
static var defaultValue: Value = .zero
static func reduce(value _: inout Value, nextValue: () -> Value) {
_ = nextValue()
}
@Joony
Joony / Setter.swift
Created November 4, 2022 09:44
Convert a property into a function (a setter) so the value can be set as part of a function pipeline, or partially applied so the property can be set in response to specific events.
class Test {
var greeting = "Hello, playground"
}
let test = Test()
func setter<O: AnyObject, V>(_ obj: O, _ keyPath: ReferenceWritableKeyPath<O, V>) -> (V) -> () {
{ [weak obj] value in obj?[keyPath: keyPath] = value }
}
@Joony
Joony / RadioGroup+Example.swift
Created November 3, 2022 11:53
A SwiftUI implementation of a simple radio group for iOS
private struct ColorToggle: View {
@Binding var isOn: Bool
let color: Color
var body: some View {
Toggle("", isOn: $isOn)
.toggleStyle(ColorToggleStyle(color: color))
.buttonStyle(.borderless)
}
@Joony
Joony / Milli_example.swift
Created October 21, 2022 10:44
Format a TimeInterval as time in milliseconds
let t: TimeInterval = 0.1337
let measurement = Measurement<UnitDuration>(value: t, unit: .seconds)
.converted(to: .milliseconds)
measurement.formatted(
.measurement(
width: .narrow,
numberFormatStyle: .number.precision(.significantDigits(3))
)
@Joony
Joony / Color+Int.swift
Created October 13, 2022 08:54
A SwiftUI extension of Color to add Int/String representation for storage
extension Color {
var sRGBA: Int {
guard let components = UIColor(self).cgColor.components?.map({ Int(0xFF * $0) }) else { return 0 }
return (components[3] << 24) | (components[0] << 16) | (components[1] << 8) | components[2]
}
var hex: String {
String(sRGBA, radix: 16, uppercase: true)
}
var named: String {
UIColor(self).accessibilityName