Skip to content

Instantly share code, notes, and snippets.

View tonyarnold's full-sized avatar

Tony Arnold tonyarnold

View GitHub Profile
import SwiftUI
public struct ChangeObserver<V: Equatable>: ViewModifier {
public init(newValue: V, action: @escaping (V) -> Void) {
self.newValue = newValue
self.newAction = action
}
private typealias Action = (V) -> Void
@tonyarnold
tonyarnold / Sequence+AnyCancellable.swift
Last active September 17, 2020 02:24
Useful extension for storing a sequence of AnyCancellable instances
import Combine
import Combine
extension Sequence where Element == AnyCancellable {
/// Stores this type-erasing cancellable collection in the specified collection.
///
/// - Parameter collection: The collection in which to store this ``AnyCancellable`` sequence.
func store<C>(in collection: inout C) where C: RangeReplaceableCollection, C.Element == Element {
forEach { $0.store(in: &collection) }
@tonyarnold
tonyarnold / NSObject+BidirectionalAssign.swift
Created September 11, 2020 05:52
Experiment to implement bidirectional assignment of values using Combine/KVO publishers
import Combine
import Foundation
extension NSObjectProtocol where Self: NSObject {
/// Assigns each unique element assigned to the key paths specified to the inverse object.
func bidirectionallyAssign<Value: Equatable, B: NSObject>(
from firstKeyPath: ReferenceWritableKeyPath<Self, Value>,
to secondKeyPath: ReferenceWritableKeyPath<B, Value>,
on otherObject: B
) -> [AnyCancellable] {
@tonyarnold
tonyarnold / NSObject+AnyCancellable.swift
Created September 11, 2020 04:34
A nifty extension that I borrowed from DeclarativeHub's ReactiveKit: https://github.com/declarativehub/reactivekit/
import Combine
import ObjectiveC.runtime
extension NSObject {
private enum AssociatedKeys {
static var CancellablesKey = "CancellablesKey"
}
/// A set that can be used to dispose of Combine cancellables.
public var cancellables: Set<AnyCancellable> {
@tonyarnold
tonyarnold / RangeReplaceableCollectionOperators.swift
Created August 25, 2020 13:29
Use this to add an operator to append items to sequences, ie: `collection += item`
extension RangeReplaceableCollection {
static func += (collection: inout Self, element: Element) {
collection.append(element)
}
static func += (collection: inout Self, element: Element?) {
if let element = element {
collection.append(element)
}
}
import Vapor
extension EventLoopFuture {
/// When the current `EventLoopFuture<Value>` is fulfilled, run the provided callback,
/// which will provide a new `EventLoopFuture`.
///
/// This allows you to dynamically dispatch new asynchronous tasks as phases in a
/// longer series of processing steps. Note that you can use the results of the
/// current `EventLoopFuture<Value>` when determining how to dispatch the next operation.
///
import Foundation
@propertyWrapper
struct StringCoded<WrappedValue: LosslessStringConvertible>: Codable {
var wrappedValue: WrappedValue
init(wrappedValue: WrappedValue) {
self.wrappedValue = wrappedValue
}
@tonyarnold
tonyarnold / CompareTools.plist
Created March 6, 2019 22:35
Git Tower & Sublime Merge Integration
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<dict>
<key>ApplicationIdentifier</key>
<string>com.sublimemerge</string>
<key>ApplicationName</key>
<string>Sublime Merge</string>
<key>DisplayName</key>
@tonyarnold
tonyarnold / MutableCollection+Move.swift
Last active April 28, 2018 15:51
Swift extension that allows moving between a single index and another index in a mutable collection
// The MIT License (MIT)
//
// Copyright © 2018 Tony Arnold (@tonyarnold)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
@tonyarnold
tonyarnold / UIKitCatchupToAppKit.swift
Last active July 16, 2021 16:10
Bring some of AppKit's strongly typed names and identifiers to UIKit
import UIKit
public extension UIStoryboard {
public struct SceneDescriptor {
public let name: UIStoryboard.Name
public let identifier: UIStoryboard.SceneIdentifier
public init(name: UIStoryboard.Name, identifier: UIStoryboard.SceneIdentifier) {
self.name = name