Тема номер раз: Занимательная многопоточка. Затронем проблемы и разновидности крэшей, с которыми может столкнуться условный программист под iOS при работе с потоками/очередями, и как с этим быть.
Сложность в том, что во время разработки их тяжко отследить, так как нет детерминированных шагов для воспроизведения. Скорее всего проблема всплывет на крэшах в Crashlytics, пострадают пользователи, а вы как Эркюль Пуаро будете изучать исходники и пытаться воспроизвести падение.
Заблуждение в Swift состоит в том, что использование структур вместо классов может излечить от всех болезней, а механизм CoW (Copy on Write) разрулит все возможные проблемы при конкурентном обновлении данных.
Пример: конкурентное добавление данных в свифтовый массив. При запуске получим EXC_BAD_ACCESS. Контейнеры данных в Swift имеют сложное строение внутри, поэтому их нужно изменять с осторожностью.
Как быть:
-Включать 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
Проблему решили линеаризацией операций по обновлению сцен на очереди, которая дергает методы 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, чтобы избежать указанных выше проблем. Плюс получите одно решение на две платформы и в два раза меньший штат разрабов