Pull to refresh

Comments 15

А вот то что разрешили не использовать self в замыканиях мне не очень нравится, так как большинство утечек памяти как раз было связано с тем что люди забывают про то что self захватывается замыканием. Найти проблему было достаточно легко, просто через поиск «.self», сейчас же это будет чуть-чуть сложнее, так как «sayHello()» может быть и другим замыканием, которое было объявлено выше. Но посмотрим как оно пойдёт, может я не прав и это будет действительно лучше.

К счастью, сделано по уму: исключение сделано для типов значений, которые вовсе не передаются по ссылке, и если есть явное указание на тип self в замыкании, например ‘execute { [self] in’. И да, я тоже запускаю поиск по ‘self.’ для поиска утечек :)

как это помогает? достаточно давно можно писать без скобок
guard let self = self else { return }
При self из числа value type можно не писать guard let self вообще, а в некоторых случаях, когда объект и так висит в памяти от начала до конца (сразу приходят в голову только синглтоны), можно просто указать [self] in вначале тела замыкания, и тоже сэкономить 5 символов в каждой строке. Как-то так :)
если висит в памяти от начала и до конца как при UIView.animate, то зачем указывать
[self] in вначале тела замыкания
?
Наверно, чтобы не заставляло дальше по тексту писать self.methodName или self.varName, — ну любят люди экономить по 5 букв, не знаю, что ещё сказать. Главное для меня то, что не убрали вообще self в замыканиях, так как это стало бы источником дополнительных ошибок.
Висят в памяти от начала и до конца работы всего приложения. Замыкание animations: @escaping () -> Void наоборот не должно иметь в себе [self] in, если вызов происходит из самого View, так как это будет подвешивать его в памяти (View держит ссылку на @escaping замыкание, а замыкание — на View. В таком случае как раз нужен [weak self] in и всё дальше как обычно.
насколько понимаю, будет подвешивать в памяти в любом случае, так как анимация происходит на главном потоке и вызов completion гарантируется?
Немного не понял вопрос, что значит гарантируется?
В нормальной ситуации (без ошибочной ссылки из стороннего объекта на замыкание и без reatin cycle, когда замыкание и View удерживают друг друга) @escaping такая ситуация встречаться не должна.
Выполнение @escaping возможно, пока жив в памяти соответствующий экземпляр замыкания. Если не сохранять ссылку на замыкание специально, то на него держит сильную ссылку порождающий экземпляр класса (в данном случае View), а также может держать держать ссылку экземпляр CFRunLoopObserver (если не ошибаюсь) главного потока, в котором код выполняется асинхронно или другого потока, хотя анимация на другом потоке выполняться не должна вообще.
Если экземпляр View уничтожается и ссылка на замыкание не хранится где-то ещё, то runloop:
1) дойдет до обработки события счётчика ссылок и обнаружит, что количество ссылок на замыкание = 0, после чего объявит использовавшуюся под него память свободной. Продолжения расчётов для анимации не произойдет;
2) runloop на главном потоке увидит наличие удерживающей ссылки от другого потока на замыкание. В этом случае я затрудняюсь ответить, что происходит. Но думаю, что скорее всего сторонний поток завершит выполнение (уже ненужной анимации, потому её и нужно исполнять на главном!), перейдет обратно по стеку, отпустит последнюю ссылку на замыкание. После чего замыкание также будет уничтожено (а возможно и весь поток, если после этого у него пустует стек и нечего больше выполнять).

Тут скорее про такое поведение в структурах, ибо там это не опасно.

Новая версия (SE-0279) предлагает новый синтаксис для конечных замыканий, который позволяет вызывать несколько замыканий в качестве параметров функции более читаемым способом. Это сводит к минимуму использование слишком большого количества скобок в сигнатуре функции.


Смотрю на код, и в новом представлении насчитываю на 4 скобки больше, чем в старой версии
Да, я тоже этот момент не понял. То, что оно нагляднее выглядит, так это за счет indentation по моему.
Количество скобок не меняется, так как круглые скобки можно и в первом примере поставить. А вот запятых меньше становится.
Но пропало слово success. ИМХО, но тогда уже лучше исппользовать вот такую верстку
load(
    url: "someURL", 
    success: { data in }, 
    failure: { error in }
)

Вот если бы ещё запятые при этом можно было не писать. А то напоминает о сишных точках с запятой в конце строки. Только тут ещё хуже, потому что после последней строчки запятая не ставится.

Было бы хорошо:
load(url: "someURL")
success: { data in

}
failure: {error in 

}


Или:
load(
    url: "someURL"
    success: { data in

    }
    failure: {error in 

    }
)
Sign up to leave a comment.

Articles