【问题标题】:Swift exit for loop from within an autoreleasepool?从自动释放池中快速退出循环?
【发布时间】:2019-10-11 05:15:27
【问题描述】:

假设我在循环中有以下内容:

for i in 0...10 {
    autoreleasepool {
        // do some crazy memory thing
    }
}

我将如何从 autoreleasepool 块中跳出 for 循环?

【问题讨论】:

    标签: swift for-loop break nsautoreleasepool


    【解决方案1】:

    我为此找到的解决方案是从 autoreleasepool 块返回一个布尔值,true 用于继续或 false 用于中断。 autoreleasepool 块显然是阻塞的。

    for i in 0...10 {
        if (
            !autoreleasepool {
                // do stuff
                // return false for break, true for continue.
                return true
            }
        ) {
            break
        }
    }
    

    【讨论】:

      【解决方案2】:

      设置一个您可以选择在自动释放池中设置的变量:

      for i in 0...10 {
          var stop = false
          autoreleasepool {
              // lots of stuff
      
              stop = true // call this if you need to stop
          }
          if stop { break }
      }
      

      【讨论】:

        【解决方案3】:

        我推断这个问题的目的是能够发布一个答案,展示autoreleasepool 实际上是一个通用方法,返回其闭包返回的任何值。有人建议可以这样做:

        for i in 0...10 {
            if (
                !autoreleasepool {
                    // do stuff
                    // return false for break, true for continue.
                    return true
                }
            ) {
                break
            }
        }
        

        虽然当我们第一次发现许多同步闭包方法实际上是返回闭包所做的任何事情的泛型时很有启发性,但我认为这并不是其应用的一个特别好的例子。如果您需要在代码中使用 cmets 来解释返回值的含义,那就是更深层次问题的代码异味。我认为rmaddy’s approach (+1) 更清晰,更容易推理。 autoreleasepool 有很好的用途,它返回与闭包相同的 Result,但这不是它,恕我直言。


        让我们考虑一个更引人注目的使用 autoreleasepool 返回类型。假设您有一些例程执行以下操作(我已删除 GCD 调用以将注意力集中在 autoreleasepool):

        func generateAllImages() {
            for index in 0 ..< imageCount {
                let image = generateImage(for: index)
                updateUserInterface(for: index, with: image)
            }
        }
        

        假设在分析应用程序的过程中,我们发现隐藏在 generateImage 中的是创建了一个自动释放对象的东西,这使得我们应用程序的峰值内存使用量真的飙升。显然,您可以执行以下操作来减少应用程序的高水位标记,在每次迭代时耗尽自动释放池:

        func generateAllImages() {
            for index in 0 ..< imageCount {
                autoreleasepool {
                    let image = generateImage(for: index)
                    updateUserInterface(for: index, with: image)
                }
            }
        }
        

        但是,如果您确认您的自动释放对象被限制在 generateImage 例程的范围内,您可以稍微整理一下:

        func generateAllImages() {
            for index in 0 ..< imageCount {
                let image = autoreleasepool { generateImage(for: index) }
                updateUserInterface(for: index, with: image)
            }
        }
        

        这不仅更简洁,而且清楚地表明了自动释放对象的创建位置。这种模式让我印象深刻,因为它非常自然且引人注目地使用了 autoreleasepool 返回其闭包返回的对象的行为。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-02-15
          • 2011-08-11
          • 1970-01-01
          • 1970-01-01
          • 2014-05-07
          • 1970-01-01
          • 2013-04-16
          相关资源
          最近更新 更多