Быстрый выход для цикла из автозапуска? - PullRequest
1 голос
/ 24 мая 2019

Предполагается, что в цикле есть следующее:

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

Как мне выйти из цикла for из блока autoreleasepool?

Ответы [ 3 ]

2 голосов
/ 24 мая 2019

Установите переменную, которую вы можете установить в пуле автоматического выпуска:

for i in 0...10 {
    var stop = false
    autoreleasepool {
        // lots of stuff

        stop = true // call this if you need to stop
    }
    if stop { break }
}
2 голосов
/ 24 мая 2019

Я предполагаю, что цель этого вопроса состояла в том, чтобы иметь возможность опубликовать ответ, показывающий, как autoreleasepool на самом деле является универсальным методом, возвращающим любое значение, возвращаемое его закрытием. Было предложено, что можно сделать:

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

Хотя это откровенно, когда мы впервые обнаруживаем, что многие из этих методов синхронного замыкания на самом деле являются обобщениями, которые возвращают то, что делает замыкание, я не думаю, что это является особенно хорошим примером его применения. Если вам нужны комментарии в вашем коде, чтобы объяснить, что означает возвращаемое значение, это запах кода для более глубокой проблемы. Я думаю, что подход Рмадди (+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 поведения возврата объекта, возвращаемого его замыканием.

2 голосов
/ 24 мая 2019

Решением, к которому я пришел, было вернуть из блока autoreleasepool логическое значение, true для продолжения или false для перерыва.блок autoreleasepool явно блокируется.

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