Created
April 11, 2020 15:03
-
-
Save DevAndArtist/f14456567df0852a5c2a4e111d1043a0 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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