Skip to content

Instantly share code, notes, and snippets.

@thillsman
Last active April 13, 2020 17:42
Show Gist options
  • Save thillsman/02594e227bb0e0a9e839dec992207094 to your computer and use it in GitHub Desktop.
Save thillsman/02594e227bb0e0a9e839dec992207094 to your computer and use it in GitHub Desktop.
Combine backport
import Foundation
@propertyWrapper
struct Published<Value> {
var projectedValue: Published { self }
var wrappedValue: Value { didSet { valueDidChange() } }
private var observations = MutableReference(
value: List<(Value) -> Void>()
)
init(wrappedValue: Value) {
self.wrappedValue = wrappedValue
}
}
private extension Published {
func valueDidChange() {
for closure in observations.value {
closure(wrappedValue)
}
}
}
class AnyCancellable {
private var closure: (() -> Void)?
init(closure: @escaping () -> Void) {
self.closure = closure
}
deinit {
cancel()
}
func cancel() {
closure?()
closure = nil
}
}
extension Published {
func sink(with closure: @escaping (Value) -> Void) -> AnyCancellable {
closure(wrappedValue)
let node = observations.value.append(closure)
return AnyCancellable { [weak observations] in
observations?.value.remove(node)
}
}
}
struct List<Value> {
private(set) var firstNode: Node?
private(set) var lastNode: Node?
}
extension List {
class Node {
var value: Value
fileprivate(set) weak var previous: Node?
fileprivate(set) var next: Node?
init(value: Value) {
self.value = value
}
}
}
extension List: Sequence {
func makeIterator() -> AnyIterator<Value> {
var node = firstNode
return AnyIterator {
let value = node?.value
node = node?.next
return value
}
}
}
extension List {
@discardableResult
mutating func append(_ value: Value) -> Node {
let node = Node(value: value)
node.previous = lastNode
lastNode?.next = node
lastNode = node
if firstNode == nil {
firstNode = node
}
return node
}
}
extension List {
mutating func remove(_ node: Node) {
node.previous?.next = node.next
node.next?.previous = node.previous
if firstNode === node {
firstNode = node.next
}
if lastNode === node {
lastNode = node.previous
}
node.next = nil
node.previous = nil
}
}
class Reference<Value> {
fileprivate(set) var value: Value
init(value: Value) {
self.value = value
}
}
class MutableReference<Value>: Reference<Value> {
func update(with value: Value) {
self.value = value
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment