🔥

Тред (Антон Давыдов)


Тема номер раз: Занимательная многопоточка. Затронем проблемы и разновидности крэшей, с которыми может столкнуться условный программист под iOS при работе с потоками/очередями, и как с этим быть.

Сложность в том, что во время разработки их тяжко отследить, так как нет детерминированных шагов для воспроизведения. Скорее всего проблема всплывет на крэшах в Crashlytics, пострадают пользователи, а вы как Эркюль Пуаро будете изучать исходники и пытаться воспроизвести падение.

Заблуждение в Swift состоит в том, что использование структур вместо классов может излечить от всех болезней, а механизм CoW (Copy on Write) разрулит все возможные проблемы при конкурентном обновлении данных.

Пример: конкурентное добавление данных в свифтовый массив. При запуске получим EXC_BAD_ACCESS. Контейнеры данных в Swift имеют сложное строение внутри, поэтому их нужно изменять с осторожностью.
notion image

Как быть: -Включать Thread Sanitizer developer.apple.com/documentation/… -Использовать примитивы синхронизации, либо попробовать swift.org/blog/swift-ato…, если задача позволяет -Оставить пометку в доке, что method is not thread safe -Перепроективать эту часть кода.

Следующая проблема — недокументируемые особенности внутрянки некоторых фреймворков. Например, SceneKit developer.apple.com/documentation/…, который в Кошельке используется для того, чтобы красивую и интерактивную карту рисовать.

Для того, чтобы не фризить мейн созданием сцены, последняя обновляется на бэкграунде, но внутри себя SceneKit использует какой-то свой shared state. В некоторый момент времени, если звёзды сойдутся, приложение может упасть из-за этого, даже если изменяются два несвязанные SCScene
notion image

Проблему решили линеаризацией операций по обновлению сцен на очереди, которая дергает методы SCNSceneRendererDelegate developer.apple.com/documentation/….

Поделитесь плиз с какими проблемами вам приходилось сталкиваться на практике и как решали?

Следующая более очевидная проблема в многопоточке — работа с UIKit объектами не на мейне. Тут, как говорится, есть нюансики. Например, с UIImage без проблем можно работать на background очереди для генерации превьюх как вот тут nshipster.com/image-resizing/.

UIView тоже можно поконфигурировать, но при попытке добавить объект в иерархию вьюх будет немного боли и есть шанс, что получите не просто ворнинг, а приложение упадет (видимо, если будете добавлять в момент лейаута или работы механизма Responder Chaining developer.apple.com/documentation/…)

Внезапная возможная проблема с Objective-C🦕 — декларация @property(atomic) NSMutableArray *array не делает операции добавления/удаления элементов массива thread safe, а только гарантирует корректное чтение и запись непосредственно ссылки на свойство array и работу ARC.

У меня был отличный курс в ЛЭТИ на эту тему в свое время, если хочется покопать тему и изучить типы блокировок (lock-based, lock-free, wait-free), в чем плюсы/минусы спинлока, узнать что такое консенсус/консенсусное число, то рекомендую материалы курса wiki.osll.ru/doku.php/cours….

А так всё это байки олдскула, всем давно понятно, что в 2021 нативная разработка не нужна. Лучше использовать браузерные технологии и современный язык javascript, чтобы избежать указанных выше проблем. Плюс получите одно решение на две платформы и в два раза меньший штат разрабов