Reputation: 1132
I want to access the value of a variable from inside a closure. But I don't want to get the changed variable, I want to get the value from the initial closure init.
In Objective-C there was no problem with that, because every "outside" variable was copied and could be accessed like a const
. Now every variable behaves like a __block
var.
-- EDIT --
i created a much simpler example. the one in objective c works, the one in swift not:
swift:
var myQueue: dispatch_queue_t = dispatch_queue_create("com.mycompany.myqueue", DISPATCH_QUEUE_CONCURRENT);
for i in 0...200 {
let startDate = NSCalendar.currentCalendar().dateByAddingUnit(NSCalendarUnit.CalendarUnitDay, value: (i+1)*(-1), toDate: NSDate.date(), options: NSCalendarOptions.MatchFirst)
dispatch_async(myQueue, {
println("\(i) - \(startDate.descriptionWithLocale(NSLocale.systemLocale()))")
})
}
Output swift (data "bullshit"):
3 - 2014 M07 30, Wed 17:33:58 GMT+02:00
...
9 - 2014 M07 24, Thu 17:33:58 GMT+02:00
10 - 2014 M07 23, Wed 17:33:58 GMT+021:30 0-
1 12 0-11 442 0-M1 0427 0 1M12201410 76 7,- M 2-0-S22 7 u0,2 2n1 010 4T1911 u4,
objective c:
for (int i = 0; i < 200; i++) {
NSDate *startDate = [[NSCalendar currentCalendar] dateByAddingUnit:NSCalendarUnitDay value:(i+1)*(-1) toDate:[NSDate date] options:NSCalendarMatchFirst];
dispatch_async(myQueue, ^(void) {
NSLog(@"%d - %@", i, startDate);
});
}
objective c output:
2014-08-03 17:30:49.893 m7[92781:611495] 1 - 2014-08-01 15:30:49 +0000
2014-08-03 17:30:49.893 m7[92781:611494] 3 - 2014-07-30 15:30:49 +0000
2014-08-03 17:30:49.894 m7[92781:611496] 4 - 2014-07-29 15:30:49 +0000
2014-08-03 17:30:49.894 m7[92781:611498] 6 - 2014-07-27 15:30:49 +0000
2014-08-03 17:30:49.894 m7[92781:611497] 5 - 2014-07-28 15:30:49 +0000
2014-08-03 17:30:49.895 m7[92781:611495] 9 - 2014-07-24 15:30:49 +0000
...
I want to access startDate
within the closure. But it's the changed value and not the inital one, from before the closure was executed.
What can I do?
Upvotes: 0
Views: 702
Reputation: 539745
Just use local variables for start/endDate in the loop:
for i in 0...6 {
let startDate = calendar.dateByAddingUnit(NSCalendarUnit.CalendarUnitDay, value: (i+1)*(-1), toDate: today, options: NSCalendarOptions.MatchFirst)
let endDate = calendar.dateByAddingUnit(NSCalendarUnit.CalendarUnitDay, value: (i)*(-1), toDate: today, options: NSCalendarOptions.MatchFirst)
self.stepCounter.queryStepCountStartingFrom(startDate, to: endDate, toQueue: NSOperationQueue.mainQueue(), withHandler: {
(numberOfSteps: NSInteger , error: NSError!) in
println("steps: \(numberOfSteps)")
})
}
Then each iteration has its own instance of the dates, and the value of the captured dates does not change.
Update: Another problem is that the Swift println()
function is not thread-safe.
That causes the garbage in your example. For debug output from concurrently running
threads, better use NSLog()
which is available in Swift as well:
dispatch_async(myQueue, {
NSLog("%d - %@", i, startDate)
})
Upvotes: 2