【问题标题】:Why is Progress.fractionCompleted exceeding 1.0?为什么 Progress.fractionCompleted 超过 1.0?
【发布时间】:2019-11-21 01:30:59
【问题描述】:

我注意到在某些情况下Progress.fractionCompleted 超过 1.0 甚至重置回 0。我在使用 MultipeerConnectivity 框架时第一次注意到它,我在其中构建了一个进度树,其中包含从 MCSession.sendResource 返回的 Progress 实例。

下面的代码重现了奇怪的行为。只需复制粘贴即可。

let childUnitCounts: [(initialCompletedUnitCount: Int64, totalUnitCount: Int64)] = [
    (9855, 34375),
    (10950, 19110),
    (9855, 37511),
    (9855, 18799),
    (9855, 42705),
    (10950, 19021), // When commenting out this line or setting the initial unit count to 0, things work as expected.
]

let parent = Progress(totalUnitCount: Int64(childUnitCounts.count))

let children: [Progress] = childUnitCounts.map { unitCount in
    let child = Progress(totalUnitCount: unitCount.totalUnitCount)
    child.completedUnitCount = unitCount.initialCompletedUnitCount

    parent.addChild(child, withPendingUnitCount: 1)

    return child
}

print(parent)

for (i, state) in childUnitCounts.enumerated() {
    children[i].completedUnitCount = state.totalUnitCount
    print(parent)
}

以上产生以下输出:

<NSProgress: 0x600000f6da40> : Parent: 0x0 (portion: 0) / Fraction completed: 0.4088 / Completed: 0 of 6  
  <NSProgress: 0x600000f6dc20> : Parent: 0x600000f6da40 (portion: 1) / Fraction completed: 0.2627 / Completed: 9855 of 37511  
  <NSProgress: 0x600000f6db80> : Parent: 0x600000f6da40 (portion: 1) / Fraction completed: 0.5730 / Completed: 10950 of 19110  
  <NSProgress: 0x600000f6dae0> : Parent: 0x600000f6da40 (portion: 1) / Fraction completed: 0.2867 / Completed: 9855 of 34375  
  <NSProgress: 0x600000f6de00> : Parent: 0x600000f6da40 (portion: 1) / Fraction completed: 0.5757 / Completed: 10950 of 19021  
  <NSProgress: 0x600000f6dd60> : Parent: 0x600000f6da40 (portion: 1) / Fraction completed: 0.2308 / Completed: 9855 of 42705  
  <NSProgress: 0x600000f6dcc0> : Parent: 0x600000f6da40 (portion: 1) / Fraction completed: 0.5242 / Completed: 9855 of 18799  
<NSProgress: 0x600000f6da40> : Parent: 0x0 (portion: 0) / Fraction completed: 0.5277 / Completed: 1 of 6  
  <NSProgress: 0x600000f6dc20> : Parent: 0x600000f6da40 (portion: 1) / Fraction completed: 0.2627 / Completed: 9855 of 37511  
  <NSProgress: 0x600000f6db80> : Parent: 0x600000f6da40 (portion: 1) / Fraction completed: 0.5730 / Completed: 10950 of 19110  
  <NSProgress: 0x600000f6de00> : Parent: 0x600000f6da40 (portion: 1) / Fraction completed: 0.5757 / Completed: 10950 of 19021  
  <NSProgress: 0x600000f6dd60> : Parent: 0x600000f6da40 (portion: 1) / Fraction completed: 0.2308 / Completed: 9855 of 42705  
  <NSProgress: 0x600000f6dcc0> : Parent: 0x600000f6da40 (portion: 1) / Fraction completed: 0.5242 / Completed: 9855 of 18799  
<NSProgress: 0x600000f6da40> : Parent: 0x0 (portion: 0) / Fraction completed: 0.5989 / Completed: 2 of 6  
  <NSProgress: 0x600000f6dc20> : Parent: 0x600000f6da40 (portion: 1) / Fraction completed: 0.2627 / Completed: 9855 of 37511  
  <NSProgress: 0x600000f6de00> : Parent: 0x600000f6da40 (portion: 1) / Fraction completed: 0.5757 / Completed: 10950 of 19021  
  <NSProgress: 0x600000f6dd60> : Parent: 0x600000f6da40 (portion: 1) / Fraction completed: 0.2308 / Completed: 9855 of 42705  
  <NSProgress: 0x600000f6dcc0> : Parent: 0x600000f6da40 (portion: 1) / Fraction completed: 0.5242 / Completed: 9855 of 18799  
<NSProgress: 0x600000f6da40> : Parent: 0x0 (portion: 0) / Fraction completed: 0.8094 / Completed: 3 of 6  
  <NSProgress: 0x600000f6de00> : Parent: 0x600000f6da40 (portion: 1) / Fraction completed: 0.5757 / Completed: 10950 of 19021  
  <NSProgress: 0x600000f6dd60> : Parent: 0x600000f6da40 (portion: 1) / Fraction completed: 0.2308 / Completed: 9855 of 42705  
  <NSProgress: 0x600000f6dcc0> : Parent: 0x600000f6da40 (portion: 1) / Fraction completed: 0.5242 / Completed: 9855 of 18799  
<NSProgress: 0x600000f6da40> : Parent: 0x0 (portion: 0) / Fraction completed: 0.8886 / Completed: 4 of 6  
  <NSProgress: 0x600000f6de00> : Parent: 0x600000f6da40 (portion: 1) / Fraction completed: 0.5757 / Completed: 10950 of 19021  
  <NSProgress: 0x600000f6dd60> : Parent: 0x600000f6da40 (portion: 1) / Fraction completed: 0.2308 / Completed: 9855 of 42705  
<NSProgress: 0x600000f6da40> : Parent: 0x0 (portion: 0) / Fraction completed: 1.0169 / Completed: 5 of 6  
  <NSProgress: 0x600000f6de00> : Parent: 0x600000f6da40 (portion: 1) / Fraction completed: 0.5757 / Completed: 10950 of 19021  
<NSProgress: 0x600000f6da40> : Parent: 0x0 (portion: 0) / Fraction completed: 1.2795 / Completed: 6 of 6  

最后一行显然应该以Fraction completed: 1.0 结尾。在注释掉childUnitCounts的最后一个元素或者设置初始单元数为0时,可以正常工作。

我认为这是一个错误,但在报告它之前,我想确保我没有遗漏任何东西。

【问题讨论】:

  • “不要在一个紧密的循环中更新 completedUnitCount。”,我猜我错过了,谢谢!我会再深入一点。至于fractionCompleted 的使用(因为它是一个浮点数,不是因为它的价值!),那部分我知道,但为了强调问题,在这里使用它。不幸的是,问题要深得多,取决于进度树的大小,fractionCompleted 有时会跳来跳去,比如从 0.9 到 0.1,然后到 1.3。我知道fractionCompleted 不应该用于检查完成,但它应该用于面向用户的文本和控件!
  • 哦,给你。想知道消失的答案发生了什么。 @matt 知道我感谢您的参与!在“不得不”断定这是一个错误之前,我仍然“希望”我遗漏了一些东西。
  • 是的。当省略(或使用 0 作为)中间值时,无论孩子有多少,事情都会正常工作。我也试过异步设置completedUnitCount,但结果是一样的。我认为not setting completedUnitCount in a tight loop 主要是出于性能原因(KVO)。
  • 此行为仅适用于 iOS 13!在 iOS 12 上完全不同。我准备宣布这是一个错误。
  • 好的,这是反馈​​ FB7463813。

标签: ios swift foundation nsprogress


【解决方案1】:

为了消除怀疑的来源,我进行了各种练习,例如在孩子进度的每次变化之前添加延迟,玩弄各种数字,甚至将整个事情翻译成 Objective-C 以确保这一点不是某种 Swift 数字问题:

int64_t totals[] = {34375, 19110, 37511, 18799, 42705, 19021};
int64_t initials[] = {9855, 10950, 9855, 9855, 9855, 10950};
int sz = 6;
NSProgress* parent = [NSProgress progressWithTotalUnitCount:sz];
NSMutableArray* children = [NSMutableArray array];
for (int i = 0; i<sz; i++) {
    NSProgress* child = [NSProgress progressWithTotalUnitCount:totals[i]];
    child.completedUnitCount = initials[i];
    [children addObject:child];
    [parent addChild:child withPendingUnitCount:1];
}
for (int i = 0; i<sz; i++) {
    NSProgress* child = children[i];
    child.completedUnitCount = totals[i];
}
NSLog(@"%@", parent);

我的结论是:

  • 即使在 Objective-C 中,上面的代码也会以 1.2795 的父级分数结束。

  • 如果 sz 小于或等于 5,则完成的父级分数最终为 1。这个问题似乎只有在孩子数量超过一定数量时才会出现。

  • 通过添加延迟来更改时间没有任何区别(此处未显示代码)。

  • 在 iOS 12 上运行的完全相同的代码总是得到一个完整的父部分 1

因此,尽管说服我 Apple 可能犯了这样的错误需要花费很多时间,但我说服了。您在 iOS 13 Foundation 中发现了一个非常严重的错误。

【讨论】:

  • 我只是希望这不是浮点数的根深蒂固的问题,因为更改单位计数值会产生其他结果(但也高于 1.0)!
猜你喜欢
  • 2010-12-19
  • 2018-03-08
  • 1970-01-01
  • 2013-10-02
  • 2016-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-28
相关资源
最近更新 更多