Skip to content

Instantly share code, notes, and snippets.

View Amzd's full-sized avatar
🚀

Casper Zandbergen Amzd

🚀
View GitHub Profile
import UIKit
/// A view that hides its content to a user's recording, broadcast or screenshot.
/// https://gist.github.com/Amzd/2652bc98a6ae098701b342d710e45aa7
@available(iOS 12, *)
@dynamicMemberLookup
class PrivacySensitiveView<ContentView: UIView>: UIView {
private var content: ContentView
private var textField = {
let textField = UITextField()
@Amzd
Amzd / GiveBackMyFirstResponder.swift
Last active October 17, 2024 12:25
Some iOS system view controllers do not give back the first responder when the view is dismissed. This remedies that by manually returning the first responder. This is not as smooth as the private UIKit way but it works.
extension UIViewController {
/// UIDocumentPickerViewController by itself does not return first responder to the view controller that presented it
/// when the cancel button is pressed after the search field was used. This function fixes that by making the previous
/// first responder, first responder again when the document picker is dismissed.
/// Normally this is handled by the private `UIViewController._restoreInputViewsForPresentation`
/// but for some reason the UIDocumentPickerViewController does not call that, and since it's closed source I don't
/// know why.
///
/// To confirm this:
/// - have a viewcontroller with a textfield
extension Image {
/// This helps achieving what `UIView.ContentMode.scaleAspectFit` and `.scaleAspectFill` do in UIImageView.contentMode
///
/// The difference between Image.containerAspectRatio (this) and SwiftUIs View.aspectRatio is that the first applies the
/// aspect ratio to the view that contains the image, rather than to the image itself.
///
/// So in the following example:
/// - The first image will scale to a square but the contentMode does not do anything to prevent stretching and wether you use .fit or .fill does not matter.
/// - The second image will resize to fit inside a square while maintaining its aspect ratio, similar to how a UIImageView with contentMode set to scaleAspectFit behaves.
/// - The third image will resize to fill inside a square while maintaining its aspect ratio similar to how a UIImageView with contentMode set to scaleAspectFill behaves.
@Amzd
Amzd / EmptyOrNil.swift
Last active June 10, 2024 13:48 — forked from casperzandbergenyaacomm/EmptyOrNil.swift
Adding readability for an if statement I often use.
protocol EmptyOrNil {
var isEmpty: Bool { get }
}
extension Optional where Wrapped: EmptyOrNil {
var isEmptyOrNil: Bool {
return self?.isEmpty ?? true
}
}
import SwiftUI
/// Reads the width of the selection box next to a List row when editing mode is .active
///
/// Note: On iOS 15 the listRowInsets do not respond to updates so if you want to offset
/// the cell you should use negative leading padding.
public struct ListSelectionBoxWidthReader<Content: View>: View {
@State private var boxWidth: CGFloat = 0
private var content: (CGFloat) -> Content
@Amzd
Amzd / DictionaryKeyPath.swift
Last active November 5, 2023 04:46 — forked from casperzandbergenyaacomm/DictionaryKeyPath.swift
Reading and writing to (possible) nested dictionaries for a given key path, using a recursive approach
// Inspired by: https://gist.github.com/dfrib/d7419038f7e680d3f268750d63f0dfae
import Foundation
public extension Dictionary {
subscript(keyPath string: Key, separator: String) -> Value? where Key == String {
get { return self[keyPath: string.components(separatedBy: separator)] }
set { self[keyPath: string.components(separatedBy: separator)] = newValue }
}
@Amzd
Amzd / StateObject.swift
Last active October 7, 2024 22:25
StateObject that works in iOS 13
import Combine
import PublishedObject // https://github.com/Amzd/PublishedObject
import SwiftUI
/// A property wrapper type that instantiates an observable object.
@propertyWrapper
public struct StateObject<ObjectType: ObservableObject>: DynamicProperty
where ObjectType.ObjectWillChangePublisher == ObservableObjectPublisher {
/// Wrapper that helps with initialising without actually having an ObservableObject yet
@Amzd
Amzd / DateRounding.swift
Created June 2, 2021 08:58 — forked from casperzandbergenyaacomm/DateRounding.swift
Rounding of date and time
import Foundation
extension Date {
/// Returns date where **-component** is rounded to its closest
/// multiple of **-amount**. Warning: month and day start at 1
/// so round(to: 6, .month) will either return month 1 or 7!
func round(to amount: Int, _ component: Calendar.Component) -> Date {
let cal = Calendar.current
var value = cal.component(component, from: self)
@Amzd
Amzd / AppendingClosures.swift
Last active May 16, 2023 19:50
Appending Closures, eg a shorthand to create one new closure that calls two closures.
// MARK: Appending closures `a + b`
/// Append closures, lhs first.
public func + <I>(lhs: @escaping (I) -> Void, rhs: @escaping (I) -> Void) -> ((I) -> Void) {
return {
lhs($0)
rhs($0)
}
}
@Amzd
Amzd / ColorPicker.swift
Last active September 29, 2024 00:36
What SwiftUI's ColorPicker should have been.
import SwiftUI
@available(iOS 14.0, *)
public struct ColorPickerWithoutLabel: UIViewRepresentable {
@Binding var selection: Color
var supportsAlpha: Bool = true
public init(selection: Binding<Color>, supportsAlpha: Bool = true) {
self._selection = selection
self.supportsAlpha = supportsAlpha