Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save palpatim/9a43d48f5ad0239fbc92c79fbda2902b to your computer and use it in GitHub Desktop.
Save palpatim/9a43d48f5ad0239fbc92c79fbda2902b to your computer and use it in GitHub Desktop.
import Foundation
import XCPlayground
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
class UnownedTester {
private static let testQueue = dispatch_queue_create("playground.unowned.tester", DISPATCH_QUEUE_SERIAL)
private static var instance: UnownedTester? = UnownedTester()
private static var startTime: NSDate!
private static let maxDuration: NSTimeInterval = 2.0
private static func invokeCallback(afterDelay delay: Int, closure: () -> ()) {
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay) * Int64(NSEC_PER_SEC))
dispatch_after(time, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
closure()
}
}
private var iterations = 0
static func startTest() {
startTime = NSDate()
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(maxDuration * Double(NSEC_PER_SEC)))
dispatch_after(time, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
print("Setting `instance` to nil")
UnownedTester.instance = nil
}
print("Starting test at \(startTime)")
instance?.test()
print("All dispatched")
let maxTime = dispatch_time(DISPATCH_TIME_NOW, Int64(6 * Double(NSEC_PER_SEC)))
dispatch_after(maxTime, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
print("Stopping execution")
XCPlaygroundPage.currentPage.finishExecution()
}
}
private func test() {
for i in 1...5 {
UnownedTester.invokeCallback(afterDelay: i) {
// Case 1: No modifiers -- block is retained
// self.printResult()
// Case 2: weak -- block is not retained
// [weak self] in
// self?.printResult()
// Case 3: weak with force unwrap -- block is not retained, crashes on iteration 3
// [weak self] in
// self!.printResult()
// Case 3: unowned -- execution never ends until Playground execution terminated because the process stopped unexpectedly. What is happening here?
// [unowned self] in
// withExtendedLifetime(self) {
// self.printResult()
// }
// Case 4: weak & withExtendedLifetime with force-unwrap, crashes on iteration 3
// [weak self] in
// withExtendedLifetime(self) {
// self!.printResult()
// }
// Case 5: weak & withExtendedLifetime with force-unwrap
[weak self] in
withExtendedLifetime(self) {
guard let _self = self else {
return
}
_self.printResult()
}
}
}
}
deinit { print(#function) }
private func printResult() {
iterations += 1
print("Iteration \(iterations)")
}
}
UnownedTester.startTest()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment