Xcode 6 iOS Создание Cocoa Touch Framework - проблемы с архитектурой
Я пытаюсь создать динамическую структуру для приложения iOS. Благодаря новой версии Xcode (6) мы можем выбрать Cocoa Touch Framework, когда мы создадим новый проект, и больше не нужно добавлять агрегированную цель, запустите script и так сделать ее. У меня нет проблем при создании фреймворка. Но когда я пытаюсь использовать его в приложении iOS, я получаю некоторые проблемы с архитектурой.
ld: warning: ignoring file /Library/Frameworks/MyFramework.framework/MyFramework, file was built for x86_64 which is not the architecture being linked (arm64): /Library/Frameworks/MyFramework.framework/MyFramework
Undefined symbols for architecture arm64:
"_OBJC_CLASS_$_MyFrameworkWebService", referenced from:
objc-class-ref in AppDelegate.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
ld: warning: ignoring file /Library/Frameworks/MyFramework.framework/MyFramework, file was built for x86_64 which is not the architecture being linked (armv7): /Library/Frameworks/MyFramework.framework/MyFramework
Undefined symbols for architecture armv7:
"_OBJC_CLASS_$_MyFrameworkWebService", referenced from:
objc-class-ref in AppDelegate.o
ld: symbol(s) not found for architecture armv7
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Ну, я попытался изменить настройки проекта и целевого объекта фреймворка (Архитектуры и Создать только допустимую архитектуру и Действительные архитектуры). Я сделал то же самое для проекта приложения iOS, но ничего не работает. Я думаю, что я чего-то не понял.
Например, когда я создаю фреймворк только для i386 (iOS Simulator), проверьте с помощью командной строки
"xcrun lipo -info MyFramework", у меня есть проблема, которая
ld: предупреждение: игнорирование файла /Library/Frameworks/MyFramework.framework/MyFramework, файл был создан для x86_64, который не связан с архитектурой (i386)...
Если кто-то может помочь мне получить фреймворк, который работает для всех архитектур iOS, включая симуляторы.
Ответы
Ответ 1
На основе всех ответов post на raywenderlich.com и gist, созданный Крис Конвей Я придумал this.
Выполняя следующие шаги, я смог создать структуру Cocoa Touch (включая файлы Swift и Objective-C), которая содержит все архитектуры как для симулятора, так и для устройства:
- Создайте новую (агрегированную) цель в своем проекте структуры
- В разделе "Фазы сборки" выберите "Добавить запуск Script" и скопируйте содержимое этот файл
- Выберите цель Совокупная цель в раскрывающемся списке Схема
- Создать целевую для агрегатной схемы
Надеюсь, это поможет:)
UPDATE: Исправлена ошибка в сущности, где пути на шаге 3 были неверными. Благодаря Tokuriku!!
ОБНОВЛЕНИЕ. В Xcode 7 и 8 нажмите "Файл" > "Создать" > "Цель..." и выберите "Другая", чтобы выбрать "Сгруппировать цель"
Ответ 2
Попробуйте выполнить следующие шаги, чтобы создать рабочую область, содержащую проект рамки и проект приложения.
Workspace:
- Создайте рабочее пространство.
Рамочный проект:
- Создайте проект iOS Cocoa touch Framework внутри рабочей области.
- Добавьте простой класс Objective C MyClass (заголовок .h и файл реализации .m) и создайте приветствие метода - (void).
- Go project Фазы сборки > Заголовки > Переместите MyClass.h из Project в Общие.
- Измените схему на проект рамки и выберите iOS simulator, а затем выполните. (Выберите iOS Device, если приложение, интегрирующее эту инфраструктуру, запускается на устройстве. Я буду продолжать использовать симулятор в этом примере)
- У вас не должно возникнуть проблемы, сборка фреймов находится в каталоге Derived Datastrong > , который вы можете найти в Организаторе.
Проект приложения:
- Создайте приложение Swift Single View внутри рабочей области.
- Перетащите выше рамки фреймворка iOS (найдено в Debug-iphonesimulator или Release-iphonesimulator) в ваш проект.
- Создайте заголовок для моста, чтобы открыть методы класса Objective C для Swift.
- Импортируйте MyClass.h в сборке заголовочного файла.
- Обратите внимание, что если определение MyClass не найдено, добавьте путь структуры Заголовки для создания настроек Контуры поиска заголовков.
- Создайте экземпляр MyClass в viewDidLoad из ViewController.swift, затем вызовите приветствия.
- Добавить фреймворк в цель > Встроенные двоичные файлы
- Измените схему на проект и выберите iOS симулятор, затем создайте.
- Вы должны иметь возможность видеть приветственные сообщения.
Обратите внимание, что в приведенном выше примере показано, как создать приложение, работающее в симуляторе. Если вам нужно создать универсальную статическую библиотеку, которая работает как на симуляторе, так и на устройствах, тогда общие шаги:
- Библиотека сборки для симулятора
- Библиотека сборки для устройства
- Объедините их с помощью lipo
В Интернете есть хорошие ссылки, здесь.
Создайте универсальный двоичный файл для фреймворка: перейдите в каталог Derived Data, затем /Build/Products, следующая команда должна помочь вам создать универсальный двоичный файл в каталоге Продукты:
lipo -create -output "framework-test-01-universal" "Debug-iphonesimulator/framework-test-01.framework/framework-test-01" "Debug-iphoneos/framework-test-01.framework/framework-test-01"
Обратите внимание, что framework-test-01 - это мое имя проекта фрейма.
Ответ 3
Ниже приведены шаги по созданию жирной (универсальной) структуры:
![enter image description here]()
![enter image description here]()
-
Запустите эту script из Products
. В этой папке создается fat Framework. (или сделайте это вручную, как описано ниже в 4. 5.)
framework_name="${$(basename $(find ./Debug-iphoneos -type d -name '*.framework' -maxdepth 1))%.*}" && \
cp -R Debug-iphoneos/$framework_name.framework ./$framework_name.framework && \
lipo -create -output "$framework_name.framework/$framework_name" "Debug-iphonesimulator/$framework_name.framework/$framework_name" "Debug-iphoneos/$framework_name.framework/$framework_name"
Или:
-
Объедините эти 2 Framework с помощью lipo с помощью этого script (замените YourFrameworkName
на ваше имя Framework)
lipo -create -output "YourFrameworkName" "Debug-iphonesimulator/YourFrameworkName.framework/YourFrameworkName" "Debug-iphoneos/YourFrameworkName.framework/YourFrameworkName"
-
Замените новую двоичную одну из существующих фреймворков:
cp -R Debug-iphoneos/YourFrameworkName.framework ./YourFrameworkName.framework
mv YourFrameworkName ./YourFrameworkName.framework/YourFrameworkName
- Прибыль:
./YourFrameworkName.framework
- - готовый к использованию жирный бинарный!. Вы можете импортировать его в свой проект!
Для проекта это не в xcworkspace
-es:
Вы также можете попытаться использовать этот смысл Но кажется, что он не работает для проектов в рабочих пространствах.
Ответ 4
То, как я это делал, похоже на vladof, но, надеюсь, немного проще. Я сделал структуру подпроектом проекта приложения.
Рамочный проект
- Создайте новую iOS Cocoa Touch Framework. Назовите это MyLib. Это создаст один MyLib.h
- Добавьте простой класс Cocoa Touch Obj-C, MyClass (.h и .m) и в реализацию .m, создайте метод, который возвращает строку, - приветствия (NSString *);
- В MyLib.h добавьте это внизу, #import "MyClass.h"
- В целевом разделе "Сборка фаз/заголовков" переместите MyClass.h из раздела "Проект" в раздел "Публикация".
- Сделайте сборку (cmd-B)
- Закройте проект
Проект приложения
- Создайте новый проект приложения Single View, будь то Swift или Obj-C. Назовите это MyApp.
- Из Finder перетащите файл проекта MyLib в раздел органайзера левой руки окна MyApp и убедитесь, что строка вставки находится чуть ниже MyApp. Это делает MyLib подпроектом MyApp. (Его можно по-прежнему использовать в других проектах)
- Нажмите на MyApp в организаторе, а затем выберите цель MyApp и выберите "Сформировать фазы".
- В целевых зависимостях щелкните знак + и добавьте MyLib.
- В Link with Libraries щелкните знак + и добавьте MyLib.framework.
Для приложения Obj-C
- В ViewController.m добавьте #import
- В viewDidLoad добавьте следующие строки:
- MyLib * x = [[MyLib alloc] init];
- NSLog (@ "% @", x.greetings);
- Запустите проект, и вы увидите сообщение в окне отладки. -
Для приложения Swift
- В ViewController.swift добавьте импорт MyLib
- в viewDidLoad, добавьте следующие строки:
- var x: MyLib = MyLib()
- println ( "(x.greetings())" ) -
Таким образом, приложение зависит от фреймворка, поэтому, если вы вносите изменения в классы инфраструктуры, вам не нужно изменять цели для создания структуры отдельно, она сначала компилирует структуру, затем приложение.
Ответ 5
Я немного изменил кого-то script для поддержки всех архитектур Simulator:
UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal
# make sure the output directory exists
mkdir -p "${UNIVERSAL_OUTPUTFOLDER}"
# Step 1. Build Device and Simulator versions
xcodebuild -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
xcodebuild -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphonesimulator VALID_ARCHS="x86_64 i386" BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
# Step 2. Copy the framework structure to the universal folder
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework" "${UNIVERSAL_OUTPUTFOLDER}/"
# Step 3. Create universal binary file using lipo and place the combined executable in the copied framework directory
lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework/${PROJECT_NAME}"
# Step 4. Convenience step to copy the framework to the project directory
cp -R "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework" "${PROJECT_DIR}"
# Step 5. Delete temporary build directory in the project directory
rm -rf "${PROJECT_DIR}/build"
# Step 6. Convenience step to open the project directory in Finder
open "${PROJECT_DIR}"
Ответ 6
Пошаговая статья о создании Cocoa Touch Frameworks с снимками экрана, найденными по этой ссылке → Как создать Cocoa сенсорную структуру
Ответ 7
Наконец, я заработал у меня!
И жаль большую желтую рамку, я понятия не имею, как ее лучше отформатировать.
Решение было получено от Claudio Romandi, но связанный с ним script имеет небольшую проблему. Я не могу комментировать его сообщение, потому что мне нужна репутация 50, поэтому мне остался без выбора, но чтобы скопировать его сообщение, чтобы иметь полное решение.
- Создайте новую (совокупную) цель в своем проекте Framework
- Выберите агрегат в рабочей области и добавьте "New Run script Phase"
-
Вставьте в него следующий код:
#!/bin/sh
UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal
# make sure the output directory exists mkdir -p "${UNIVERSAL_OUTPUTFOLDER}"
# Step 1. Build Device and Simulator versions xcodebuild -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION}
-sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build xcodebuild -target "${PROJECT_NAME}" -configuration ${CONFIGURATION} -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
# Step 2. Copy the framework structure (from iphoneos build) to the universal folder cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework" "${UNIVERSAL_OUTPUTFOLDER}/"
# Step 3. Copy Swift modules (from iphonesimulator build) to the copied framework directory cp -R "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/Modules/${PROJECT_NAME}.swiftmodule/." "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Modules/${PROJECT_NAME}.swiftmodule"
# Step 4. Create universal binary file using lipo and place the combined executable in the copied framework directory lipo -create
-output "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework/${PROJECT_NAME}"
# Step 5. Convenience step to copy the framework to the project directory cp -R "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework" "${PROJECT_DIR}"
# Step 6. Convenience step to open the project directory in Finder open "${PROJECT_DIR}"
-
Выберите "Агрегат в выпадающем списке схем"
- Сборка, все готово!
Проблема заключалась в том, что каталог симулятора указывал на несуществующий каталог, меняя "Framework" на "$ {PROJECT_NAME}" в 2-х местах, сделал трюк:)
Ответ 8
Несколько дополнительных точек вокруг подхода, совместно используемого vladof, которые более применимы к быстродействующим платформам
- script в связанной ссылке требуется модификация для копирования всех файлов из iphonesimulator и iphoneos, так как у swift есть отдельные скомпилированные файлы для arm и i386
- Убедитесь, что у вас есть ARCHS = "x86_64" ONLY_ACTIVE_ARCH = НЕТ в сборке для iphonesimulator, чтобы избежать проблем с компоновщиками для симулятора
- Убедитесь, что ваш интерфейс/класс расширяет NSObject, иначе вы столкнетесь с проблемами при попытке использовать код в swift (он будет жаловаться на невозможность создания объекта using().