Xcode 6 и Embedded Frameworks поддерживаются только в iOS8

При использовании встроенного фреймворка (dyld) в Xcode 6.0.1 с целью развертывания меньше, чем iOS 8, я получаю:

  • Сборка успешна
  • Ошибка загрузки библиотеки времени выполнения

Ошибка:

dyld: Library not loaded: @rpath/ObjectiveLyricsTouch2.framework/ObjectiveLyricsTouch2        
Referenced from: /private/var/mobile/Containers/Bundle/Application/DC65ACA9-98E5-46CD-95F8-829D3416F6C0/musiXmatch.app/musiXmatch
Reason: image not found
(lldb) 

15 ответов

Некоторое время я думал, что это и моя проблема, но для обычных приложений (без расширения iOS-8) вам просто нужно изменить один параметр сборки в своей случайной цели Xcode 6 iOS Universal Framework (установить тип Mach-O). в статическую библиотеку):

Установите статическую библиотеку

После этого не должно быть проблем с iTunes Connect и iOS 7:)

Итак, покопавшись, я вышел с решением

Предполагается, что у вас есть MyEmbeddedFramework.framework для добавления в приложение, сделайте это

  1. Удалите MyEmbeddedFramework.framework на вкладке "Общие"> "Встроенные двоичные файлы".
  2. Удалите Фазы сборки> Скопировать Фазу "Каркасы", если там есть MyEmbeddedFramework.framework.
  3. Чистая папка сборки
  4. Переместите MyEmbeddedFramework.framework в раздел void Embedded Frameworks.
  5. Теперь вы увидите, что XCode6 создает новую фазу сборки> Встроенные фреймворки (не вы, это делается автоматически)
  6. Теперь, если у вас есть 5, он должен работать без ошибок.

Итак, чтобы напомнить, чтобы это работало, вы должны увидеть MyEmbeddedFramework.framework в

A) Общая информация> Встроенные двоичные файлы Общие> Встроенные двоичные файлы Встроенные двоичные файлы">

Б) Фаза сборки> Встроенные фреймворки Фаза сборки> Встроенные фреймворки Встроенные фреймворки">

Он отлично работал на iPhone5/iOS8, а не на iPhone4S/iOS7, где я получаю:

dyld: библиотека не загружена: @rpath/ObjectiveLyricsTouch2.framework/ObjectiveLyricsTouch2 Ссылка на: /var/mobile/Applications/739D9C44-3B91-4D4F-805B-83BE66C9CBCA/musiXmatch.app/musiXmatch найдена подходящая причина: найдено Нашел: 739D9C44-3B91-4D4F-805B-83BE66C9CBCA / musiXmatch.app / Каркасы / ObjectiveLyricsTouch2.framework / ObjectiveLyricsTouch2

Проблема была в EmbeddedFramework. Мне пришлось

1) Установите для архитектуры значение по умолчанию. 2) Установите для Valid Architectures: armv7, armv7s и armv64 (как Apple предполагает, что armv64 необходим для работы Embedded Frameworks).

Тогда я смог запустить приложение со встроенным фреймворком на

  • iPhone5S / iPhone5C iOS8
  • iPhone5S / iPhone5C iOS7
  • iPod 5-го поколения / iOS7
  • iPhone4S/iOS7
  • iPhone4 / iOS7

В любом случае при отправке в iTunesConnect я получаю несколько ошибок для минимально необходимой версии:

  • Минимальная версия OS фреймворка "..." недействительна. Минимальное значение - iOS 8.0;
  • Неверная архитектура: приложения, которые включают в себя и расширение приложения, и фреймворк, должны поддерживать arm64;

Проблемы встраиваемых фреймворков

На данный момент нет способа использовать встроенную среду для обмена кодом между приложением и виджетом, чтобы он работал на iOS 8, а также на iOS 7 и более ранних версиях.

Вот еще немного чтения по этому вопросу http://atomicbird.com/blog/ios-app-extension-tips

Фреймворки против iOS 7

Если вы делитесь кодом между приложением и расширением, хороший способ сделать это - создать собственную встроенную среду для хранения кода. На iOS 8 он будет загружаться динамически для обоих случаев, так что все готово.

Если вы все еще поддерживаете iOS 7 (или более раннюю версию), это не так очевидно. Встроенные фреймворки там не работают. В Руководстве по программированию расширений приложений легко заметить, что вы можете использовать dlopen для решения этой проблемы. При таком подходе вы пишете код для динамической загрузки платформы во время выполнения, а не полагаетесь на то, что iOS загружает ее для вас, если вы убедились, что код работает на версии iOS, которая поддерживает это.

Но как вы используете этот код на iOS 7? Вы не Если ваш общий код находится во встроенной платформе, его невозможно выполнить на iOS 7. Он просто недоступен.

Подход dlopen может быть полезен, если вам нужен только общий код на iOS 8. Если он вам нужен на iOS 7, вам нужно включить его в цель приложения. И как только вы это сделаете, вам не нужны рамки. Вы все еще можете использовать фреймворк для расширения приложения, но на самом деле это бесполезно. Вы будете заниматься созданием фреймворка, но не получите от него никакой выгоды. Просто включите общий код в обе цели.

А из руководства по расширению Apple https://developer.apple.com/library/ios/documentation/General/Conceptual/ExtensibilityPG/ExtensibilityPG.pdf

Если вы ссылаетесь на встроенную платформу из содержащегося в ней приложения, вы все равно можете развернуть ее на версиях iOS более старых, чем 8.0, даже несмотря на то, что встроенные платформы недоступны в этих версиях.

Более подробно о документации Apple Я узнал о команде dlopen, которая используется для выполнения связывания библиотек при некоторых условиях, в зависимости от версий системы и поддерживаемых библиотек.

Пример использования dlopen: Является ли функция 'dlopen()' закрытым API?

Итак, давайте посмотрим на решение, предоставленное Apple Docs:

Развертывание содержащего приложения на более старых версиях iOS

Если вы ссылаетесь на встроенную платформу из содержащегося в ней приложения, вы все равно можете развернуть ее на версиях iOS более ранних, чем 8.0, даже если встроенные платформы недоступны в этих версиях.

Механизм, который позволяет вам сделать это, - команда dlopen, которую вы используете для условного связывания и загрузки пакета инфраструктуры. Эта команда используется в качестве альтернативы связыванию во время сборки, которое можно указать в редакторе целей Xcode General или Build Phases. Основная идея состоит в том, чтобы связывать встроенные фреймворки с приложением, которое вы используете, только при работе в iOS 8.0 или новее

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

После вызова dlopen получите доступ к встроенным классам каркаса с помощью следующего типа оператора:

MyLoadedClass *loadedClass = [[NSClassFromString (@"MyClass") alloc] init];

ВАЖНЫЙ

Если целевое приложение, содержащее ваше приложение, ссылается на встроенную среду, оно должно включать архитектуру arm64, иначе оно будет отклонено App Store.

Чтобы настроить проект Xcode расширения приложения, чтобы использовать условные ссылки

  1. Для каждого из ваших расширений приложения установите цель развертывания на iOS 8.0 или более позднюю версию, как обычно. Сделайте это в разделе "Информация о развертывании" на вкладке "Общие" в целевом редакторе XCode.
  2. Для вашего содержащего приложения установите цель развертывания как самую старую версию iOS, которую вы хотите поддерживать.
  3. В вашем содержащем приложении обусловливайте вызовы команды dlopen в ходе проверки времени выполнения для версии iOS с помощью метода systemVersion. Вызывайте команду dlopen только в том случае, если приложение содержит iOS 8.0 или более позднюю версию. При выполнении этого вызова обязательно используйте Objective-C, а не Swift.

Некоторые API-интерфейсы iOS используют встроенные фреймворки с помощью команды dlopen. Вы должны обусловить использование этих API так же, как и при непосредственном вызове dlopen. Эти API относятся к непрозрачному типу CFBundleRef:

CFBundleGetFunctionPointerForName
CFBundleGetFunctionPointersforNames

И из класса NSBundle:

нагрузка
loadAndReturnError:
classNamed:

В содержащем приложении, которое вы развертываете на версиях iOS более старых, чем 8.0, вызывайте эти API только в ходе проверки времени выполнения, которая гарантирует, что вы работаете в iOS 8.0 или более поздней версии, и вызывайте эти API, используя Objective-C.

Исправлена ​​ошибка в xcode 6.1.1

с помощью vim или vi откройте файл project.pbxproj.

В конце файла (поиск 8.1) будет раздел Begin XCBuildConfiguration.

Ищите свои рамки.

В любом случае, даже если цель развертывания была установлена ​​на 7.1 через Xcode -> general в настройках цели, запись в файле содержала 8.1 для отладки и выпуска

Вот старый раздел файла выглядит так:

CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = ENFramework/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";

Новый раздел выглядит так:

CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = ENFramework/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 7.1;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";

Теперь мы не получаем сообщение об ошибке только как предупреждение (но оно работает на устройстве iOS 7.1): ld: warning: встроенные файлы dylibs/frameworks работают только на iOS 8 или более поздней версии.

Это похоже на ошибку xcode, которая неправильно устанавливает различные цели ios, а затем вызывает ошибку.

Я установил для Mach-O Type значение EXECUTABLE, и оно сработало для меня. Установка его в Static, Dynamic или Bundle приводила к другим ошибкам при запуске.

Цель> "Ваше приложение" > Настройки сборки> Связывание> Тип Mach-O> Исполняемый файл

Просто для записи... У меня была эта проблема при изменении проекта с iOS8 на тип развертывания iOS7.

Приложение использовало cocoapods и никаких пользовательских встроенных фреймворков.

Мне пришлось сменить основной проект на две цели
заявка
Применение испытаний

Изменение типа Mach-O на статическое (ответ сверху).

Тогда на проекте cocoapods. Под каждым подподпроектом меняем тип Mach-O на статический, оставляя настройку основного подпроекта Mach-O пустым.

Мы попытались запустить последнюю версию кода на следующих конфигурациях:

iOS 8+ - iPhone 5s iOS 7.1.2 - iPhone 4 iOS 6.1.3 - iPad 4

Приложение работает нормально на всех трех устройствах, но во время компиляции в Xcode присутствует предупреждение. "встроенные dylibs/frameworks работают только на iOS 8 или новее"

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

Кроме того, обнаружил ссылку, где в Apple разработчик заявил, что это ошибка https://devforums.apple.com/message/999579

Я решаю эту проблему следующим образом: используйте одну и ту же цель развертывания как в целевой программе "Embedded Framework", так и в "главной программе".

Итак, временно, я сказал нет динамической библиотеке, в то время как многие устройства на iOS 7. Как я решил свою проблему. Мне нужно было lib для передачи модели между приложением и расширением. Итак, я поместил свою модель в строку JSON в общий контейнер. И это работает как шарм.

Удалите рамки использования! из вашего PodFile, если вы хотите, чтобы Framework работал в iOS 7.0. то есть выполните команду pod deintegrate, измените ваш PodFile, а затем снова запустите команду pod install

Кроме того, после этого мне пришлось добавить все.h файл Framework в файл Bridging, что решило проблему. Также удалите импортируемую TestLibrary из файлов swift

Когда вы используете динамическую библиотеку на ios, вы должны подписать код библиотеки. В Xcode 6 вы должны выбрать "Code Sign On Copy". А с Xcode5 вы должны подписать библиотеку самостоятельно с помощью скрипта запуска. лайк:

LOCATION="${BUILT_PRODUCTS_DIR}"/"${FRAMEWORKS_FOLDER_PATH}"
IDENTITY="iPhone Developer: xxxxx"
codesign --verbose --force --sign "$IDENTITY" "$LOCATION/BeeFramework.framework/BeeFramework"

У меня была ошибка при обновлении до xcode 7.3. И у меня было решение для меня. - Изменить цели в проекте стручков -> 7.0 - Надеюсь, что это полезно! атака

iOS Dynamic framework до iOS v8

Dynamic frameworkон же Embedded framework поддерживается начиная с iOS v8, но можно попробовать изменитьMach-O type [О] дляDynamic Library(который установлен по умолчанию для поддерживаемой цели)

Ошибка динамического связывания [О программе]

      dyld: Library not loaded: @rpath/<some_path>

Это ошибка динамического компоновщика, которая связывает двоичный файл во время загрузки или выполнения.

[Словарный запас]

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

Моим решением было использовать Pod и убедиться, что вы раскомментировали "use_frameworks!" линия.

Другие вопросы по тегам