Capture values by Closures in different background threads.


#1

Assume we have this code:

Immediately two Timer's closures captured two copy of initial values of instance Test, with internal num values is 0.

//: Playground - noun: a place where people can play

import UIKit

var str = "Hello, playground"

struct Test {
var num = 0
mutating func newNum(new: Int ) {
num = new
}
}

var test = Test ()

Timer . scheduledTimer (withTimeInterval: 1.0 , repeats: false ) { (timer) in
print ( "tick" )
test . newNum (new: 8 )
}

Timer . scheduledTimer (withTimeInterval: 2.0 , repeats: false ) { (timer) in
print ( "tack, test.num = \ ( test . num )" )
}

CFRunLoopRun ()

We have next log:
tick
tack, test.num = 8

Why Timer's two closure return to us value 8 and not 0?

···

--
Седых Александр


(Jordan Rose) #2

When not using a capture list, Swift closures always refer to variables, not to their values. So here you’re not capturing copies, you’re capturing the actual variable ‘test’, and the mutating function will update it. (If you did capture a copy, it would be immutable, and the call to ‘newNum(new:)’ would be rejected.)

On top of that, ‘test’ is a top-lovel variable, so it doesn’t even need to be captured at all. The closures can just refer to it globally.

Hope that clears things up. There are some more examples of this <https://developer.apple.com/library/prerelease/content/documentation/Swift/Conceptual/Swift_Programming_Language/Expressions.html#//apple_ref/doc/uid/TP40014097-CH32-ID544> in the Swift Programming Language book.

Jordan

···

On Nov 30, 2016, at 02:38, Седых Александр via swift-users <swift-users@swift.org> wrote:

Assume we have this code:

Immediately two Timer's closures captured two copy of initial values of instance Test, with internal num values is 0.

//: Playground - noun: a place where people can play

import UIKit

var str = "Hello, playground"

struct Test {
    var num = 0
    mutatingfunc newNum(new: Int) {
        num = new
    }
}

var test = Test()

Timer.scheduledTimer(withTimeInterval: 1.0, repeats: false) { (timer) in
    print("tick")
    test.newNum(new: 8)
}

Timer.scheduledTimer(withTimeInterval: 2.0, repeats: false) { (timer) in
    print("tack, test.num = \(test.num)")
}

CFRunLoopRun()

We have next log:
tick
tack, test.num = 8

Why Timer's two closure return to us value 8 and not 0?

--
Седых Александр
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(Jeremy Pereira) #3

Assume we have this code:

Immediately two Timer's closures captured two copy of initial values of instance Test, with internal num values is 0.

//: Playground - noun: a place where people can play

import UIKit

var str = "Hello, playground"

struct Test {
    var num = 0
    mutatingfunc newNum(new: Int) {
        num = new
    }
}

var test = Test()

Timer.scheduledTimer(withTimeInterval: 1.0, repeats: false) { (timer) in
    print("tick")
    test.newNum(new: 8)
}

Timer.scheduledTimer(withTimeInterval: 2.0, repeats: false) { (timer) in
    print("tack, test.num = \(test.num)")
}

CFRunLoopRun()

We have next log:
tick
tack, test.num = 8

Why Timer's two closure return to us value 8 and not 0?

Because the first timer changed the value to 8 when it expired one second before.

···

On 30 Nov 2016, at 10:38, Седых Александр via swift-users <swift-users@swift.org> wrote:

--
Седых Александр
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users