iOS приложение с фреймворком падает на устройстве: dyld: Library not loaded, Xcode 6 Beta
Причина проблемы
Ваша ошибка — классическая проблема с динамическими библиотеками в iOS, особенно остро проявившаяся в Xcode 6 Beta из-за изменений в работе Swift runtime. Дело в том, что Xcode 6 Beta автоматически не добавляет ваш фреймворк в Embedded Binaries (встроенные бинарники) приложения. В симуляторе система находит библиотеку благодаря общим путям поиска, но на реальном устройстве приложение запускается в изолированной песочнице, где фреймворк физически отсутствует — отсюда и dyld: Library not loaded.
Ключевой момент: Linked Frameworks and Libraries (связывание) — это только указание линковщику, что ваш код зависит от фреймворка. Но чтобы фреймворк попал на устройство, его нужно встроить (embed) в пакет приложения. В Xcode 6 Beta этот шаг не автоматизирован для пользовательских фреймворков.
Решение
Вам нужно явно добавить фреймворк в Embedded Binaries вашего основного таргета. Сделайте следующее:
- В Project Navigator выберите ваш проект (синяя иконка).
- Выберите таргет MyApp (ваше основное приложение).
- Перейдите на вкладку General.
- Прокрутите вниз до раздела Embedded Binaries.
- Нажмите на плюс (
+) и выберитеMyFramework.frameworkиз списка.
После этого Xcode скопирует фреймворк в папку Frameworks внутри вашего .app пакета. Теперь при запуске на устройстве dyld сможет найти библиотеку по пути @rpath/MyFramework.framework/MyFramework.
Дополнительные проверки
- Build Phases → Embed Frameworks: Убедитесь, что в вашем таргете есть фаза сборки Embed Frameworks (Xcode 6 Beta иногда не создаёт её автоматически). Если её нет — добавьте вручную через Editor → Add Build Phase → Add Embed Frameworks Build Phase и укажите ваш фреймворк.
- Runpath Search Paths: В Build Settings вашего таргета проверьте
Runpath Search Paths. Для динамических фреймворков значение должно быть@executable_path/Frameworks(или@loader_path/Frameworksдля расширений). Xcode обычно устанавливает это автоматически, но на всякий случай проверьте. - Clean Build Folder: После изменения настроек обязательно сделайте Product → Clean Build Folder (зажмите Option), затем пересоберите проект.
Полный рабочий пример
После всех исправлений ваш проект должен выглядеть так в настройках таргета MyApp:
General:
- Linked Frameworks and Libraries: MyFramework.framework (Required)
- Embedded Binaries: MyFramework.framework
Build Settings:
- Runpath Search Paths: @executable_path/Frameworks
Теперь при сборке на устройство фреймворк будет скопирован в MyApp.app/Frameworks/MyFramework.framework, и dyld успешно загрузит его при запуске.
Если проблема сохраняется — проверьте, что ваш фреймворк собран как динамическая библиотека (Mach-O Type = Dynamic Library), а не статическая. В Xcode 6 Beta для Swift-фреймворков это стандартное поведение.
<<Альтернативный подход: использование статической библиотеки или встраивание через скрипт
Если вы не хотите заморачиваться с настройками Embedded Binaries, есть два обходных пути:
1. Превратить фреймворк в статическую библиотеку
В Xcode 6 Beta Swift-фреймворки по умолчанию динамические. Вы можете изменить Mach-O Type на Static Library в Build Settings вашего фреймворка. Тогда код скомпилируется прямо в исполняемый файл приложения, и проблема с dyld исчезнет. Минус — увеличится размер бинарника, и вы не сможете использовать фреймворк для расширений (Today Widget, Share Extension), так как они требуют динамической загрузки.
2. Добавить скрипт в Build Phases
Если Xcode 6 Beta упорно не хочет встраивать фреймворк, добавьте в Build Phases таргета приложения новый Run Script с таким кодом:
# Встраиваем фреймворк вручную
FRAMEWORK_NAME="MyFramework"
FRAMEWORK_PATH="${BUILT_PRODUCTS_DIR}/${FRAMEWORK_NAME}.framework"
DESTINATION="${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}"
mkdir -p "$DESTINATION"
cp -R "$FRAMEWORK_PATH" "$DESTINATION"
Этот скрипт скопирует фреймворк в папку Frameworks внутри .app после каждой сборки. Он менее элегантен, но работает, если стандартные методы подводят.
Рекомендую всё же разобраться с Embedded Binaries — это правильный способ для Xcode 6 Beta и всех последующих версий.
Ответов пока нет.
Войдите чтобы оставить ответ