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) 

Ответ 1

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

Set it to Static Library

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

Ответ 2

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

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

  • Удалить MyEmbeddedFramework.framework на вкладке Общие > Встраиваемые двоичные файлы
  • Удалите фазы сборки > Фазы "Фаза копирования", если у вас есть MyEmbeddedFramework.framework.
  • Очистить папку сборки
  • Переместите файл MyEmbeddedFramework.framework в разделе Void Embedded Frameworks.
  • Теперь вы увидите, что XCode6 (не вы, это делается автоматически) создается новой фазой Build > Embedded Frameworks.
  • Теперь, если у вас 5, он должен работать без erros.

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

A) Общие > Встраиваемые двоичные файлы General > Embedded Binaries

B) Фаза сборки > Встроенные структуры Build Phase > Embedded Frameworks

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

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

Проблема была в EmbeddedFramework. Я должен был

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

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

  • iPhone5S/iPhone5C iOS8
  • iPhone5S/iPhone5C iOS7
  • iPod 5th gen/iOS7
  • iPhone4S/iOS7
  • iPhone4/iOS7

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

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

Embedded Framework Issues

Ответ 3

В настоящее время нет возможности использовать встроенную инфраструктуру для совместного использования кода между приложением и виджетами и запускать его на 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, хотя встроенные фреймворки недоступны в этих версиях.

Ответ 4

Исправлена ​​ошибка в 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: предупреждение: встроенные dylibs/frameworks работают только на iOS 8 или более поздней версии

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

Ответ 5

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

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

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

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

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

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

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

После вызова dlopen, обратитесь к встроенным кластерным классам, используя следующий тип оператора:

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

ВАЖНО

Если ваши целевые ссылки для приложения привязаны к встроенной инфраструктуре, она должна включить архитектуру arm64 или отклонить приложение Магазин.

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

  • Для каждого из ваших поддерживаемых расширений приложений задайте цель развертывания как обычно, iOS 8.0 или новее. Сделайте это в разделе "Информация о развертывании" раздел вкладки "Общие" в целевом редакторе Xcode.
  • Для вашего приложения, содержащего приложение, установите цель развертывания как старейшую версию iOS, которую вы хотите поддержать.
  • В вашем поддерживающем приложении условно вызовы команды 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.

Ответ 6

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

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#999579

Ответ 7

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

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

Ответ 8

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

Ответ 9

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

Ответ 10

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

В приложении используются cocoapods и нестандартные встроенные фреймворки.

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

Применение Application-Test

Изменение типа Mach-O для статического (из вышеприведенного ответа).

Затем на проекте cocoapods. При каждом проекте sub pod изменение типа Mach-O на статическое, оставив основной параметр Project Mach-O Project пустым.

Ответ 11

Когда вы используете динамическую библиотеку на ios, вы должны закодировать подписанную библиотеку. В Xcode 6 вы должны выбрать "Кодовая подпись". И с Xcode5 вы должны подписывать библиотеку самостоятельно с помощью run script. например:

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

Ответ 12

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

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

Ответ 13

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

Ответ 14

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

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