Xcode 6 iOS создание Cocoa Touch Framework-проблемы с архитектурой
Я пытаюсь создать динамическую структуру для приложения iOS. Благодаря новой версии Xcode (6) мы можем выбрать Cocoa Touch Framework при создании нового проекта, и больше нет необходимости добавлять агрегатную цель, запускать скрипт и так далее. У меня нет проблем, когда я строю каркас. Но когда я пытаюсь использовать его внутри приложения 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)
Ну, я попытался изменить настройки проекта и цели framework (Архитектуры и построить допустимую архитектуру только & допустимые архитектуры). Я сделал то же самое для проекта приложения iOS, но ничего не работает. Кажется, я чего-то не понял.
например, когда я создаю фреймворк только для i386 (iOS Simulator), проверьте с помощью командной строки "xcrun lipo-info MyFramework", у меня есть проблема, которая
ld: предупреждение: игнорирование файла / библиотеки / фреймворков / MyFramework.рамки/MyFramework, файл был построен для x86_64, который не архитектура связывается (i386)...
Если кто-то может помочь мне получить структуру, которая работает для всех архитектур iOS, включая тренажеры.
9 ответов
на основе всех ответов post on raywenderlich.com и суть создано Крис Конвей Я придумал этой.
выполнив следующие шаги, я смог построить Cocoa Touch framework (включая файлы Swift и Objective-C), который содержит все архитектуры как для симулятора, так и для устройства:
- создайте новую (агрегатную) цель в проекте вашей структуры
- под "Этапы сборки" выберите "Добавить скрипт запуска" и скопируйте содержимое этот файл
- выберите the совокупный элемент на схемы выбор выпадающего
- построить the цель на the совокупный схемы
надеюсь, что это помогает :)
обновление: Исправлена ошибка в gist, где пути в шаге #3 были неправильными. Спасибо Tokuriku!!
обновление в Xcode 7 и 8 выберите Файл>Создать>цель... и там выберите" другую " группу, чтобы выбрать Aggregate target
выполните следующие действия, чтобы создать рабочую область, содержащую проект фреймворка и проект приложения.
рабочее место:
- создайте рабочее пространство.
в рамках проекта:
- создать iOS какао касания рамки проект внутри рабочей области.
- добавить простой класс Objective C MyClass (заголовок .H и файл реализации .m), и создать метод - (пустота)приветствую.
- Go project Собрать Фаз>заголовки > перейти MyClass.h С проект to общественные.
- изменить схему на рамочный проект и выбрать iOS simulator, потом строить. (Выберите устройство iOS если приложение, которое интегрирует эту структуру работает на устройстве. Я буду продолжать использовать симулятор в этом примере)
- у вас не должно быть создание проблемы, сборка фреймворка находится в вашем Данные, который вы можете найти в организатор.
проект приложения:
- создайте приложение Swift Single View внутри рабочей области.
- перетащите выше iOS simulator framework сборки (найдено в Debug-iphonesimulator или Release-iphonesimulator) к вашему проекту.
- создайте заголовок моста для отображения цели C методы класса в Swift.
- Импорт MyClass.h в файле заголовка моста.
- обратите внимание, что если определение MyClass не найдено, добавьте framework заголовки путь для создания настроек Пути Поиска Заголовка.
- создать экземпляр MyClass в viewDidLoad ViewController.Свифт!--20-->, тогда звоните поздравления.
- добавить фреймворк в Target > встроенные двоичные файлы
- изменить схема проекта приложения и выберите iOS simulator, потом строить.
- вы должны иметь возможность видеть поздравительные сообщения.
обратите внимание, что в приведенном выше примере показано, как создать приложение, которое работает в симулятор. Если вам нужно создать универсальную статическую библиотеку, которая работает как симулятор и устройства, то общие шаги:
- создать библиотека для симулятор
- создать библиотека устройства
- объединить их с помощью Липо
есть хорошие ссылки в интернете об этом!--108-->здесь например.
создайте универсальный двоичный файл для framework: перейдите в каталог производных данных framework, затем /Строительства/Продукты, следующая команда должна помочь вам создать универсальный двоичный файл в продукты каталог:
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"
отметим, что фреймворк-тест-01 - это имя моего рамочного проекта.
вот шаги по созданию fat (universal) Framework:
Set
ONLY_ACTIVE_ARCH=NO
наBuild Settings
в вашем проекте.- построить библиотеку для симулятора
- построить библиотеку для устройства
открыть в консоли
Products
папка для вашего фреймворка (вы можете открыть его с помощью папки open framework иcd ..
от там)
-
Run этот скрипт С
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 фреймворка, используя Липо по этому скрипту (replace
YourFrameworkName
в свой Имя фреймворка)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
- готов к использованию fat binary! вы можете импортировать его в ваш проект!
для проекта, что не в xcworkspace
- es:
вы также можете попробовать использовать в этом суть но похоже, что она не работает для проектов в рабочих пространствах.
то, как я это сделал, похоже на vladof, но, надеюсь, немного проще. Я сделал фреймворк подпроектом проекта app.
в рамках проекта
- создайте новую платформу iOS Cocoa Touch. Назовите это MyLib. Это создаст единый MyLib.h
- добавьте простой класс Cocoa Touch Obj-C, MyClass (.ч. & м )и в осуществлении.m, создайте метод, который возвращает строку, - (NSString *)приветствия;
- В Проекте "MyLib".h, добавьте это внизу, #импорт " MyClass.h"
- в разделе этапы/заголовки сборки цели переместите MyClass.h из раздела проекта в раздел Public.
- выполните сборку (cmd-B)
- закрыть проект
проект приложения
- создайте новый проект приложения с одним представлением, Swift или Obj-C. назовите его MyApp.
- из Finder перетащите файл проекта MyLib в левый раздел организатора MyApp окно и убедитесь, что строка вставки находится чуть ниже MyApp. Это делает MyLib подпроектом MyApp. (Его все еще можно использовать таким же образом в других проектах)
- нажмите MyApp в организаторе, а затем выберите цель MyApp и выберите фазы сборки.
- в целевой зависимости, щелкните знак " + "и добавить "MyLib".
- в ссылке с библиотеками щелкните знак + и добавьте MyLib.рамки.
для приложения Obj-C
- In Файл ViewController.m, добавить #import
- в viewDidLoad добавьте следующие строки:
- MyLib * x = [[MyLib alloc] init];
- NSLog (@ "%@ " , x.привет);
- запустите проект и вы увидите сообщение в окне отладки. -
для быстрого приложения
- В ViewController.Свифт, добавить "MyLib" импорт
- в viewDidLoad добавьте следующие строки:
- ВАР х: библиотеки MyLib = MyLib ()
- println ("(x.привет ())") -
делая это таким образом, приложение зависит от фреймворка, поэтому, если вы внесете изменения в классы фреймворка, вам не придется менять цели для создания фреймворка отдельно, он просто скомпилирует фреймворк сначала, а затем приложение.
Я немного изменил чей-то скрипт для поддержки всех архитектур симулятора:
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's directory
cp -R "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework" "${PROJECT_DIR}"
# Step 5. Delete temporary build directory in the project's directory
rm -rf "${PROJECT_DIR}/build"
# Step 6. Convenience step to open the project's directory in Finder
open "${PROJECT_DIR}"
несколько дополнительных моментов вокруг подхода, разделяемого vladof, которые более применимы к фреймворкам на основе swift
- скрипт в связанной ссылке нуждается в модификации, чтобы скопировать все файлы из iphonesimulator и iphoneos, так как swift имеет отдельные скомпилированные файлы для arm и i386
- убедитесь, что у вас есть ARCHS="x86_64" ONLY_ACTIVE_ARCH=нет в сборке для iphonesimulator, чтобы избежать проблем компоновщика для симулятора
- убедитесь, что ваш интерфейс / класс расширяет NSObject, иначе вы столкнетесь с проблемами при попытке использовать код в swift (он будет жаловаться на невозможность создания объекта с помощью ().
наконец, я получил его, чтобы работать на меня! И извините за большую желтую рамку, я понятия не имею, как отформатировать ее лучше.
решение пришло от Клаудио Романди, но связанный скрипт имеет незначительную проблему. Я не могу комментировать его сообщение, потому что мне нужна репутация 50, поэтому у меня мало выбора, кроме как скопировать его сообщение, чтобы иметь полное решение..
- создайте новую (агрегатную) цель в своем рамочном проекте
- выберите агрегат в рабочей области и добавьте "новый этап запуска скрипта"
-
поместите в него следующий код:
#!/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's directory cp -R "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework" "${PROJECT_DIR}" # Step 6. Convenience step to open the project's directory in Finder open "${PROJECT_DIR}"
выберите агрегат в раскрывающемся списке выбор схемы
- построить, вы сделали!
проблема заключалась в том, что каталог симулятора указывал на несуществующий каталог, изменяя "Framework" на "${PROJECT_NAME} " в 2 местах, сделал трюк :)
Извините, что я позволил этой теме открыться так долго... Некоторые из вас правильно ответили на мой вопрос. Когда я написал этот вопрос, я не поймал, что было два куска в полной (также называемой жирной) структуре (готовой к использованию). Один для устройств iOS и один для симулятора. Когда я обнаружил, что я сделал сценарий с помощью команды lipo для слияния двух срезов и автоматически получил полную структуру.