【问题标题】:How can I get initial closure variable in Swift?如何在 Swift 中获取初始闭包变量?
【发布时间】:2014-08-03 12:35:42
【问题描述】:

我想从闭包内部访问变量的值。但是我不想获取更改后的变量,我想从初始闭包init中获取值。

在 Objective-C 中这没有问题,因为每个“外部”变量都被复制并且可以像 const 一样访问。现在每个变量的行为都像 __block var。

-- 编辑--

我创建了一个更简单的示例。 Objective c 中的一个有效,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()))")
        })
}

输出迅速(数据“废话”):

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,

目标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);
    });
}

目标c输出:

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
...

我想在闭包中访问startDate。但这是在执行闭包之前更改的值,而不是初始值。

我能做什么?

【问题讨论】:

  • 您所说的“这是一个更改的值而不是初始值”是什么意思? startDate 在执行 handler clousure 期间是否发生变化?您的代码没有说明这一点(startDate 既没有作为 inout 参数传递,也没有在 clousure 内更改它)。
  • @akashivskyy:闭包块被称为异步,因此(在此版本中)它可能会使用后续迭代的 startDate。在 Swift 中,变量是通过引用捕获的,因此它们的行为类似于 Objective-C 的 __block 变量。

标签: swift closures


【解决方案1】:

只需在循环中使用局部变量作为开始/结束日期:

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)")
    })
}

然后每次迭代都有自己的日期实例,以及 捕获的日期不会改变。

更新: 另一个问题是 Swift println() 函数不是线程安全的。 这会导致您的示例中的垃圾。用于同时运行的调试输出 线程,最好使用NSLog(),它在 Swift 中也可用:

dispatch_async(myQueue, {
    NSLog("%d - %@", i, startDate)
})

【讨论】:

  • @boxi:奇怪。它已经用dispatch_after(...) 对其进行了测试,它运行良好。很抱歉,它不适合您。
  • 我在 gcd 中添加了一个具有相同问题的新示例。一切都是 finde,我在主线程中运行它,但我运行的是串行的。
  • @boxi: println() 不是线程安全的!使用NSLog("%d - %@", i, startDate),Swift 输出似乎很好。
  • 哦。我不知道这个。真丢脸。 -.-
猜你喜欢
  • 1970-01-01
  • 2022-01-15
  • 2015-03-09
  • 1970-01-01
  • 2018-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-20
相关资源
最近更新 更多