Skip to content

Instantly share code, notes, and snippets.

@DevAndArtist
Created April 11, 2020 15:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DevAndArtist/f14456567df0852a5c2a4e111d1043a0 to your computer and use it in GitHub Desktop.
Save DevAndArtist/f14456567df0852a5c2a4e111d1043a0 to your computer and use it in GitHub Desktop.
import PlaygroundSupport
import Dispatch
let page = PlaygroundPage.current
page.needsIndefiniteExecution = true
struct Weak<T> {
struct _ObjectBox {
weak var object: AnyObject?
}
enum _Variant {
case objectBox(_ObjectBox)
case value(T?)
}
var _variant: _Variant
var value: T? {
get {
switch _variant {
case .objectBox(let box):
return box.object as! T?
case .value(let value):
return value
}
}
set {
_variant = Self._variant(from: newValue)
}
}
init(_ value: T?) {
self._variant = Self._variant(from: value)
}
static func _variant(from value: T?) -> _Variant {
switch value {
case .some(let wrapped) where type(of: wrapped) is AnyObject.Type:
let box = _ObjectBox(object: wrapped as AnyObject)
return .objectBox(box)
case .none where T.self is AnyObject.Type:
let box = _ObjectBox(object: .none)
return .objectBox(box)
default:
return .value(value)
}
}
}
class A {
deinit {
print(#function)
}
}
struct B {}
var a: A? = A()
var b: B? = B()
var weak_a_1 = Weak(a)
var weak_a_2 = Weak<A>(.none)
var weak_b_1 = Weak(b)
var weak_b_2 = Weak<B>(.none)
print(weak_a_1.value as Any) // .some(A)
print(weak_a_2.value as Any) // .none
print(weak_b_1.value as Any) // .some(B)
print(weak_b_2.value as Any) // .none
a = .none
b = .none
// prints "deinit"
print(weak_a_1.value as Any) // .none | released
print(weak_a_2.value as Any) // .none
print(weak_b_1.value as Any) // .some(B) | expected copy
print(weak_b_2.value as Any) // .none
a = A()
b = B()
protocol P {}
extension P {
var weaklyCaptured: () -> Void {
let type = Swift.type(of: self)
let weak = Weak(self)
return {
switch weak.value {
case .some:
print("\(type) - some")
case .none:
print("\(type) - none")
}
}
}
}
extension A: P {}
extension B: P {}
let a_closure = a.map(\.weaklyCaptured)!
let b_closure = b.map(\.weaklyCaptured)!
a_closure() // A - some
b_closure() // B - some
a = .none
b = .none
// prints "deinit"
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
a_closure() // A - none // released
b_closure() // B - some
page.finishExecution()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment