🔥

Тред #9


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

Когда пользователь нажимает на иконку приложения на устройстве, система заменяет текущий процессией только что созданным и передает ему управление.

Ваше приложение загружается в память устройства, где-то на этом этапе производится ASLR и система подгружает утилиту dylib, которая начинает загружать библиотеки в память.

Алгоритм загрузки зависимостей давольно простой - это обычный DFS. Загрузка библиотеки в память происходит после того, как загружены все прямые и транзитивные зависимости этой библиотеки.

Как только все библиотеки загружены, управление передается приложению, через вызов функции main и ваш AppDelegate получает вызов соответствующего метода.

Так на что же тратится время? В основном, весь процесс замедляется за счет безопастности. Помимо применения ASLR, дополнительная безопасность вашего приложения и всех его компонент осуществляется при помощи сверки подписи.

dylib не может загружать в память какие угодно библиотеки, для каждой загружаемой зависимости, необходимо сверить подпись и подтвердить, что она была выпущена либо разработчиком приложения, либо Apple.

Как раз эта проверка и съедает львиную часть драгоценного времени при запуске вашего проекта.

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

Для смены типа связывания ваших внутренних тагретов,смените тип связки на MACH_O_TYPE = staticlib, в настройках проекта.

Будьте внимательны при работе с ресурсами. Так как статический фреймворк не копируется в бандл приложения, ресурсы содержащиеся в этом фреймворке туда тоже не попадут.

Создайте отдельный таргет в вашем проекте с MACH_O_TYPE = mh_bundle и поместите туда все свои картинки, xib файлы и прочие ресурсы. Затем укажите его в фазе Copy Bundle Resources вашего приложения. Теперь этот бандл будет лежать рядом с исполняемым файлом вашего проекта.

Осталось задать новый путь к ресурсам, при помощи указания пути относительно основного бандла

let resourcePath = Bundle.main.path(forResource: "MyBundle", ofType: "bundle")

Теперь вы можете использовать ресурсы вместе со статическими библиотеками!

Из опыта работы в такой молодой и успешной компании, трюк с изменением типа связки помог увеличить количество клиентов приложения на 30%

Как оказалось, время запуска приложения играет огромную роль в при вызове такси, заказе еды или оплате услуг. У кого приложение быстрее, того и любят больше