В чем разница между статической и динамической библиотекой в iOS?

Ответ

Статическая библиотека (.a или статический .framework) линкуется с кодом приложения на этапе компиляции. Ее код становится неотъемлемой частью исполняемого файла (бинарника).

Динамическая библиотека (.dylib или динамический .framework) линкуется на этапе запуска приложения (runtime). Код библиотеки находится в отдельном файле, который загружается в память и может использоваться несколькими процессами.

Сравнение: Критерий Статическая библиотека Динамическая библиотека
Время линковки Компиляция (compile-time) Загрузка (runtime)
Размер приложения Увеличивает, так как код копируется в бинарник Не увеличивает (кроме заголовков), но библиотека должна быть доставлена с приложением
Обновление Требует пересборки приложения Можно заменить (с ограничениями в iOS)
Разделение кода Нет, код вшит в приложение Да, одна копия в памяти для нескольких процессов (системные библиотеки)
Загрузка Мгновенная, код уже в бинарнике Небольшая задержка при запуске

iOS-специфика:

  1. Embedding: Сторонние динамические фреймворки (.framework) должны быть внедрены (Embedded Binaries) в бандл приложения для iOS, иначе оно не запустится. Системные фреймворки (например, Foundation.framework) уже присутствуют в iOS.
  2. App Store & Swift: Swift-библиотеки не могут быть статически линкованы в системную кэш-память, поэтому Swift-зависимости часто доставляются как динамические фреймворки или через Swift Package Manager, который управляет линковкой.

Как добавить в Xcode:

  • Статическая: Добавить в "Link Binary With Libraries" (обычно .a или .framework).
  • Динамическая: Добавить в "Link Binary With Libraries" и в "Embed Frameworks" (для .framework).

Ответ 18+ 🔞

А, ну ты про эту вечную пляску с линковкой, да? Весьма познавательно, блядь. Слушай, сейчас разжуем, как есть.

Представь, что ты собираешься в поход. Статическая библиотека — это как если бы ты взял с собой консервный нож, приваренный нахуй к поясу. Намертво, блядь. Он всегда с тобой, ты им сразу можешь пользоваться, но и таскать его придётся везде, даже если консервов нет. Вес рюкзака (читай — размер бинарника) увеличивается, зато никаких сюрпризов.

А динамическая библиотека — это как если бы ты договорился с местным аборигеном: «Слушай, мужик, я тебе пивом, а ты мне, если что, нож на время дашь». То есть код лежит отдельным файлом (.dylib или .framework), и приложение, когда запускается, его подзывает: «Эй, браток, дай-ка сюда твои функции!». Загружается в память и работает. Плюс — один такой «абориген» (библиотека) может нескольким «туристам» (процессам) ножи выдавать. Экономия места в системе.

А теперь, сука, самое интересное — iOS-специфика. Тут Apple такие правила установила, что волосы дыбом.

Ты не можешь просто так взять и сказать системе: «Вот, держи мою динамическую библиотеку, положи её себе в системную папку». Низззя! Поэтому все твои сторонние динамические фреймворки ты обязан запихнуть прямо в бандл своего приложения, в папку Frameworks/. Это называется Embed. Если не заэмбедишь — приложение просто пизданулось при запуске, будет кричать, что библиотеку не нашло.

Системные фреймворки (Foundation, UIKit) — они уже там, в системе, их только линковать нужно.

И да, про Swift отдельная песня. Язык молодой, блядь, нестабильный. Apple не разрешает статически линковать Swift-библиотеки в системный кэш, чтобы, если там ABI поменяется, всё не полетело к ебеням. Поэтому все твои Swift-зависимости почти всегда таскаются как динамические фреймворки прямо внутри твоего же приложения. Swift Package Manager (SPM) эту всю магию за тебя делает, кстати, если правильно настроен.

Короче, памятка для Xcode, чтобы не облажаться:

  • Статическая либа (.a или статический .framework):

    • Кидаешь файлы в проект.
    • Идешь в Build Phases -> Link Binary With Libraries, добавляешь её туда.
    • Всё. Она теперь намертво вшита в твой бинарник.
  • Динамический фреймворк (.framework):

    • ШАГ 1 (линковка): Точно так же — Build Phases -> Link Binary With Libraries. Добавляешь.
    • ШАГ 2 (внедрение, самое главное!): Ищешь там же Embed Frameworks. Добавляешь тот же самый фреймворк и туда! Выбираешь Embed & Sign.
    • Если этого не сделать — получишь красивый краш при запуске. Проверено, епта.

Вот и вся философия. Статика — проще, но раздувает бинарник. Динамика — гибче, но с ней больше возни на iOS, и надо не забыть эту самую «закладку» в приложение положить. Выбирай, что для твоего случая важнее.