cocoa ios8 xcode6 dynamic-library ios-universal-framework

Xcode 6 iOS Creación de un marco Cocoa Touch-Problemas de arquitecturas



ios8 xcode6 (9)

Aquí hay unos pasos para crear el marco gordo (universal):

  1. Establezca ONLY_ACTIVE_ARCH=NO en la Build Settings en su proyecto.

    • Crear biblioteca para el simulador
    • Crear biblioteca para el dispositivo
  2. Abra en la carpeta de Products consola para su marco (puede abrirlo desde la carpeta de Open Framework y desde allí desde el cd .. )

  1. Ejecute este script desde la carpeta Products . Crea un marco gordo en esta carpeta. (o hágalo manualmente como se explica a continuación en 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"

O:

  1. Combine estos 2 marcos utilizando lipo con este script (reemplace YourFrameworkName por el nombre de su Framework)

    lipo -create -output "YourFrameworkName" "Debug-iphonesimulator/YourFrameworkName.framework/YourFrameworkName" "Debug-iphoneos/YourFrameworkName.framework/YourFrameworkName"

  2. Reemplace con uno nuevo binario de los marcos existentes:

    cp -R Debug-iphoneos/YourFrameworkName.framework ./YourFrameworkName.framework mv YourFrameworkName ./YourFrameworkName.framework/YourFrameworkName

  1. Profit: ./YourFrameworkName.framework - ¡ es un binario gordo listo para usar! ¡Puedes importarlo a tu proyecto!

Para el proyecto, eso no está en xcworkspace -es:

También puede intentar utilizar this Pero parece que no funciona para proyectos en espacios de trabajo.

Estoy tratando de hacer un marco dinámico para una aplicación de iOS. Gracias a la nueva versión de Xcode (6) podemos seleccionar un Marco de Trabajo Cocoa cuando creamos un nuevo proyecto y ya no hay necesidad de agregar un objetivo agregado, ejecutar un script y así crear uno. No tengo problemas cuando construyo el marco. Pero cuando intento usarlo dentro de una aplicación iOS, tengo algunos problemas de arquitectura.

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)

Bueno, he intentado cambiar la configuración del proyecto de marco y el objetivo (Arquitecturas y compilación, Arquitectura válida únicamente y Arquitecturas válidas). He hecho lo mismo para el proyecto de la aplicación iOS pero nada funciona. Creo que hay algo que no entendí.

Por ejemplo, cuando construyo un marco para solo i386 (simulador de iOS) verifico con la línea de comando "xcrun lipo -info MyFramework", tengo un problema que

ld: advertencia: ignorando el archivo /Library/Frameworks/MyFramework.framework/MyFramework, el archivo se creó para x86_64, que no es la arquitectura que se está vinculando (i386) ...

Si alguien puede ayudarme a obtener un marco que funcione para todas las arquitecturas iOS, incluidos los simuladores.


¡Finalmente, lo tengo para mí! Y lo siento por el gran marco amarillo, no tengo idea de cómo formatearlo mejor.

La solución vino de Claudio Romandi, pero el guión vinculado tiene un pequeño problema. No puedo hacer ningún comentario sobre su publicación porque necesito 50 de reputación, así que me queda poco para copiar su publicación para tener una solución completa.

  1. Cree un nuevo objetivo (Agregado) en su Proyecto Marco
  2. Seleccione el agregado en el espacio de trabajo y agregue una "Nueva fase de ejecución de script"
  3. Pon el siguiente código en él:

    #!/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}"

  4. Seleccione el agregado en el menú desplegable de selección de esquema

  5. ¡Construye, ya terminaste!

El problema era que el directorio del simulador apuntaba a un directorio no existente, cambiando "Framework" a "$ {PROJECT_NAME}" en 2 lugares lo hizo :)


Basado en todas las respuestas, la publicación en raywenderlich.com y la gist creada por Chris Conway, se me ocurrió this .

Ejecutando los siguientes pasos pude construir un framework Cocoa Touch (incluyendo archivos Swift y Objective-C) que contiene todas las arquitecturas tanto para el simulador como para el dispositivo:

  1. Cree un nuevo objetivo (Agregado) en el proyecto de su marco
  2. En "Crear fases", selecciona "Agregar secuencia de comandos de ejecución" y copia el contenido de este archivo
  3. Seleccione el objetivo Agregado en el menú desplegable Selección de esquema
  4. Construya el objetivo para el esquema agregado

Espero eso ayude :)

ACTUALIZACIÓN: Se corrigió un error en la esencia donde las rutas en el paso # 3 eran incorrectas. Gracias a Tokuriku !!

ACTUALIZACIÓN En Xcode 7 y 8, haga clic en Archivo> Nuevo> Destino ... y seleccione "Otro" grupo para seleccionar el objetivo Agregado


Cambié un poco el guión de alguien para admitir todas las arquitecturas del simulador:

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}"


La forma en que lo hice es similar a vladof, pero espero que sea un poco más simple. Hice el marco un subproyecto del proyecto de la aplicación.

Proyecto de marco

  • Crea un nuevo iOS Cocoa Touch Framework. Llámalo MyLib. Esto creará un solo MyLib.h
  • Agregue una clase simple Cocoa Touch Obj-C, MyClass (.h & .m) y en la implementación de .m, cree un método que devuelva una cadena, - (NSString *) saludos;
  • En MyLib.h, agrégalo cerca de la parte inferior, #import "MyClass.h"
  • En la sección Crear fases / encabezados del objetivo, mueva MyClass.h de la sección Proyecto a la sección Público.
  • Haz una compilación (cmd-B)
  • Cierre el proyecto

Proyecto de aplicación

  • Cree un nuevo proyecto de aplicación de vista única, Swift u Obj-C. Llámalo MyApp.
  • Desde el Finder, arrastre su archivo de proyecto MyLib a la sección del organizador de la izquierda de su ventana MyApp y asegúrese de que la línea de inserción esté justo debajo de MyApp. Esto hace que MyLib sea un subproyecto de MyApp. (Todavía se puede usar de la misma manera en otros proyectos)
  • Haga clic en MyApp en el organizador y luego seleccione el objetivo MyApp y seleccione Build Phases.
  • En Dependencias de destino, haga clic en el signo + y agregue MyLib.
  • En Enlace con bibliotecas, haga clic en el signo + y agregue MyLib.framework.

Para una aplicación Obj-C

  • En ViewController.m, agregue # import
  • En viewDidLoad, agregue las siguientes líneas:
  • MyLib * x = [[MyLib alloc] init];
  • NSLog (@ "% @", x.greetings);
  • Ejecute el proyecto y debería ver el mensaje en la ventana de depuración. -

Para una aplicación Swift

  • En ViewController.swift, agregue importar MyLib
  • en viewDidLoad, agregue las siguientes líneas:
  • var x: MyLib = MyLib ()
  • println ("(x.greetings ())" -

Al hacerlo de esta manera, la aplicación depende del marco, por lo que si realiza un cambio en las clases de marco, no tiene que cambiar los objetivos para construir el marco por separado, primero compilará el marco primero y luego la aplicación.


Lo siento, dejé este tema abierto durante tanto tiempo ... Algunos de ustedes han respondido correctamente a mi pregunta. Cuando escribí esta pregunta que no capté, había dos cortes en un marco completo (también llamado gordo) (listo para usar). Uno para los dispositivos iOS y otro para el simulador. Cuando descubrí que hice una secuencia de comandos con el comando lipo para fusionar las dos partes y obtener automáticamente un marco completo.


Pocos puntos adicionales en torno al enfoque compartido por vladof son más aplicables a Frameworks basados ​​rápidamente

  1. El script en el enlace asociado necesita modificación para copiar todos los archivos de iphonesimulator y iphoneos ya que el swift tiene archivos compilados por separado para arm y i386
  2. Asegúrese de tener ARCHS = "x86_64" ONLY_ACTIVE_ARCH = NO en la compilación para iphonesimulator para evitar problemas con el enlazador para el simulador
  3. Asegúrese de que su interfaz / clase amplíe NSObject, de lo contrario se encontrará con problemas cuando intente usar el código rápidamente (se quejará de que no pueda crear objetos usando ().

Pruebe los siguientes pasos para crear un espacio de trabajo que contenga un proyecto de marco y un proyecto de aplicación.

Espacio de trabajo:

  • Crea un espacio de trabajo.

Proyecto de marco:

  • Cree un proyecto iOS Cocoa touch Framework dentro de Workspace.
  • Agregue una clase simple de Objective C MyClass (header .h y archivo de implementación .m) y cree un método - (void) saludos .
  • Vaya a Project Build Phases > Headers > Mueva MyClass.h de Project a Public .
  • Cambie el esquema al proyecto marco y elija el simulador iOS , luego compile. (Elija Dispositivo iOS si la aplicación que integra este marco se ejecuta en el dispositivo. Continuaré usando el simulador en este ejemplo)
  • No debe tener problemas para compilar, la construcción del marco se encuentra en su directorio de Datos Derivados que puede encontrar en el Organizador .

Proyecto de aplicación:

  • Cree una aplicación Swift Single View dentro de Workspace.
  • Arrastre sobre la compilación del marco del simulador de iOS (se encuentra en Debug-iphonesimulator o Release-iphonesimulator ) en su proyecto.
  • Cree un encabezado puente para exponer los métodos de la clase Objective C a Swift.
  • Importe MyClass.h en el archivo de encabezado de puente.
  • Tenga en cuenta que si no se encuentra la definición de MyClass, entonces agregue la ruta de Encabezados de marco de las Rutas de búsqueda de encabezado de Configuración de compilación.
  • Crea una instancia de MyClass en viewDidLoad de ViewController.swift , luego llama a saludos .
  • Agregar framework a Target> Binarios incrustados
  • Cambia el esquema al proyecto de la aplicación y elige el simulador iOS , luego compila.
  • Debería poder ver los mensajes de saludo.

Tenga en cuenta que el ejemplo anterior muestra cómo crear una aplicación que se ejecuta en el simulador . Si necesita crear una biblioteca estática universal que se ejecute tanto en el simulador como en los dispositivos , los pasos generales son:

  • Crear biblioteca para el simulador
  • Crear biblioteca para el dispositivo
  • Combínalos usando lipo

Hay buenas referencias en la web sobre esto, aquí por ejemplo.

Crear un binario universal para el framework: navegue hasta el directorio de datos derivados del framework y / Build / Products , el siguiente comando debería ayudarlo a crear un binario universal en el directorio 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"

Tenga en cuenta que framework-test-01 es mi nombre de proyecto de framework.