¿Cómo exportar el Marco Cocoa Touch “gordo” (para Simulador y Dispositivo)?

Con Xcode 6 obtenemos la capacidad de crear nuestros propios Cocoa Frameworks dynamics de Cocoa Frameworks .

enter image description here

Porque:

  • El simulador todavía usa la biblioteca de 32-bit

  • a partir del 1 de junio de 2015, las actualizaciones de la aplicación enviadas a la tienda de aplicaciones deben incluir soporte de 64 bits y estar comstackdas con el iOS 8 SDK ( developer.apple.com )

Tenemos que crear una gran biblioteca para ejecutar proyectos en dispositivos y simuladores. es decir, admite 32 y 64 bits en Frameworks.

Pero no encontré ningún manual, cómo exportar Universal Fat Framework para una futura integración con otros proyectos (y compartir esta biblioteca con alguien).

Aquí están mis pasos para reproducir:

  1. Establezca ONLY_ACTIVE_ARCH=NO en la Build Settings

    enter image description here

  2. Añadir soporte armv7 armv7s arm64 i386 x86_64 a Architectures (seguro)

enter image description here

  1. Build Framework y ábralo en Finder:

enter image description hereenter image description here

  1. Agregar este marco a otro proyecto

Resultado actual:

Pero al final todavía tengo problemas con la ejecución del proyecto con este marco en dispositivos y simulador a la vez.

  • si tomo framework de la carpeta Debug-iphoneos – funciona en dispositivos y obtiene errores en los simuladores: ld: symbol(s) not found for architecture i386

     xcrun lipo -info CoreActionSheetPicker 

    Arquitecturas en el archivo gordo: CoreActionSheetPicker son: armv7 armv7s arm64

  • si tomo Framework de la carpeta Debug-iphonesimulator , funciona en simuladores. y tengo un error en el dispositivo: ld: symbol(s) not found for architecture arm64

     xcrun lipo -info CoreActionSheetPicker 

    Arquitecturas en el archivo gordo: CoreActionSheetPicker son: i386 x86_64

Entonces, ¿cómo crear un marco dynamic que funcione en dispositivos y simuladores?

Esta respuesta se relaciona con Xcode 6 iOS Creación de un Marco Cocoa Touch: problemas de architecture, pero no está duplicado.


Actualizar:

Encontré un “truco sucio” para este caso. Ver mi respuesta a continuación . Si alguien conoce la forma más conveniente, ¡házmelo saber!

La realidad de esta respuesta es: julio de 2015. Es muy probable que las cosas cambien.

TLDR;

Actualmente, Xcode no cuenta con herramientas para la exportación automática del framework universal fat, por lo que el desarrollador debe recurrir al uso manual de la herramienta lipo . Además, de acuerdo con este radar, antes de presentarlo al desarrollador de AppStore que es el consumidor de framework también debe usar lipo para quitar segmentos de simulador de un framework.

Sigue una respuesta más larga


Hice una investigación similar en el tema (el enlace al final de la respuesta).

No había encontrado ninguna documentación oficial sobre la distribución, por lo que mi investigación se basó en la exploración de los foros de Desarrolladores de Apple, proyectos de Cartago y Reino y mis propios experimentos con xcodebuild , lipo , herramientas de codesign .

Aquí está la cita larga (con un poco de marcado de mi parte) de Apple Developer Forums hilo Exportar aplicación con marco incrustado :

¿Cuál es la forma correcta de exportar un marco desde un proyecto de marco?

Actualmente, la única forma es exactamente lo que has hecho:

  • Construye el objective para el simulador y el dispositivo iOS.
  • Navega a la carpeta DerivedData de Xcode para ese proyecto y lipos los dos binarios en un solo marco. Sin embargo, cuando construya el objective del marco en Xcode, asegúrese de ajustar la configuración de destino ‘Construir architecture activa solamente’ a ‘NO’. Esto permitirá a Xcode construir el objective para múltiples tipos de binarty (arm64, armv7, etc.). Esta sería la razón por la cual funciona desde Xcode pero no como un binario independiente.

  • También querrá asegurarse de que el esquema esté configurado en una comstackción de versión y comstackr el objective de infraestructura contra versión. Si aún obtiene un error de biblioteca no cargada, verifique las divisiones de código en el marco.

  • Utilice lipo -info MyFramworkBinary y examine el resultado.

lipo -info MyFrameworkBinary

El resultado es i386 x86_64 armv7 arm64

  • Los frameworks universales modernos incluirán 4 sectores, pero podrían incluir más: i386 x86_64 armv7 arm64 Si no ve al menos este 4 podría ser debido a la configuración Build Active Architecture.

Esto describe el proceso más o menos lo mismo que @skywinder lo hizo en su respuesta.

Así es como Carthage usa lipo y Realm usa lipo .


DETALLE IMPORTANTE

Hay un radar: Xcode 6.1.1 y 6.2: los marcos de iOS que contienen rebanadas de simuladores no pueden enviarse a la App Store y una larga discusión al respecto en Realm # 1163 y Carthage # 188 que terminaron en una solución especial:

antes de enviarlo a AppStore, los binarios de la infraestructura de iOS deben eliminarse de las secciones del simulador

Carthage tiene un código especial: CopyFrameworks y la documentación correspondiente:

Este script funciona en torno a un error de envío de App Store provocado por binarios universales.

El reino tiene una secuencia de comandos especial: strip-frameworks.sh y la documentación correspondiente:

Este paso es necesario para solucionar un error de envío de App Store al archivar binarios universales.

También hay un buen artículo: Eliminación de architectures no deseadas de bibliotecas dinámicas en Xcode .

Yo mismo utilicé Realm’s strip-frameworks.sh que funcionó perfectamente para mí sin ninguna modificación, aunque, por supuesto, cualquiera puede escribir uno desde cero.


El enlace a mi tema que recomiendo leer porque contiene otro aspecto de esta pregunta: firma de código – Creación de marcos iOS / OSX: ¿es necesario codificarlos antes de distribuirlos a otros desarrolladores?

Esta no es una solución tan clara, pero solo hay forma de que encuentre:

  1. Establezca ONLY_ACTIVE_ARCH=NO en la Build Settings

    • 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 .. )

enter image description hereenter image description here

  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 3. 4. )

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 proyecto, eso no en Espacios de trabajo:

También puedes intentar usar esta esencia como se describe aquí . Pero parece que no funciona para proyectos en espacios de trabajo.

La respuesta de @Stainlav fue muy útil, pero lo que hice fue comstackr dos versiones del framework (una para el dispositivo y otra para el simulador) y luego agregué la siguiente Run Script Phase para copiar automáticamente el marco precomstackdo requerido para la architecture en ejecución.

 echo "Copying frameworks for architecture: $CURRENT_ARCH" if [ "${CURRENT_ARCH}" = "x86_64" ] || [ "${CURRENT_ARCH}" = "i386" ]; then cp -af "${SRCROOT}/Frameworks/Simulator/." "${SRCROOT}/Frameworks/Active" else cp -af "${SRCROOT}/Frameworks/Device/." "${SRCROOT}/Frameworks/Active" fi 

De esta forma, no tengo que usar lipo para crear un marco de trabajo gordo, ni Realm’s strip-frameworks.sh para eliminar las divisiones innecesarias al enviar a App Store.

Básicamente para esto encontré una muy buena solución. solo necesitas seguir estos sencillos pasos.

  1. Crea un marco táctil de cocoa.
  2. Establezca el código de bit habilitado en No.
  3. Seleccione su objective y elija esquemas de edición. Seleccione Ejecutar y elija Liberar de la pestaña Información.
  4. No se requiere otra configuración.
  5. Ahora construya el marco para cualquier simulador mientras el simulador se ejecuta en la architecture x86.
  6. Haga clic en el grupo de Productos en Project Navigator y encuentre el archivo .framework.
  7. Haga clic derecho sobre él y haga clic en Mostrar en el buscador. Copie y pegue en cualquier carpeta, personalmente prefiero el nombre ‘simulador’.
  8. Ahora construya el marco para dispositivos iOS generics y siga los pasos 6 a 9. Simplemente cambie el nombre de la carpeta a ‘dispositivo’ en lugar de ‘simulador’.
  9. Copie el archivo .framework del dispositivo y péguelo en cualquier otro directorio. Prefiero el súper directorio inmediato de ambos. Entonces la estructura del directorio ahora se convierte en:
    • Escritorio
    • dispositivo
      • MyFramework.framework
    • simulador
      • MyFramework.framework
    • MyFramework.framework Ahora abra la terminal y el cd en el escritorio. Ahora comience a escribir el siguiente comando:

lipo -create ‘device / MyFramework.framework / MyFramework’ ‘simulator / MyFramework.framework / MyFramework’ -output ‘MyFramework.framework / MyFramework’

y eso es. Aquí fusionamos el simulador y la versión del dispositivo del binario MyFramework presente dentro de MyFramework.framework. Obtenemos un marco universal que construye para todas las architectures, incluidos el simulador y el dispositivo.

Mi respuesta cubre los puntos siguientes:

  • Hacer un marco que funcione tanto para el simulador como para el dispositivo

  • ¿Cómo exportar el Marco Cocoa Touch “gordo” (para Simulador y Dispositivo ambos)?

  • Símbolos indefinidos para la architecture x86_64

  • ld: símbolo (s) no encontrado (s) para la architecture x86_64

Pasos 1: Primero crea tus marcos con el objective del simulador

Pasos 2: después del éxito del proceso de creación del simulador, cree ahora para su estructura la selección de objectives del dispositivo o la selección de dispositivos iOS generics.

Paso 3: Ahora selecciona tu objective de framework y para eso En “Build Phases” selecciona “Add Run Script” y copia el código de script siguiente

Paso 4: Ahora, finalmente, comstack de nuevo y tu marco de trabajo está listo para la compatibilidad tanto del simulador como del dispositivo. ¡¡¡¡Viva!!!!

[Nota: debemos tener ambos marcos compatibles listos antes del paso 4 final (el simulador y la architecture del dispositivo son compatibles, si no, por favor, siga los pasos 1 y 2 arriba correctamente)

Ver la imagen de referencia:

enter image description here

enter image description here

Ponga el código debajo del área del caparazón:

 #!/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 (if it exists) to the copied framework directory SIMULATOR_SWIFT_MODULES_DIR="${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/Modules/${PROJECT_NAME}.swiftmodule/." if [ -d "${SIMULATOR_SWIFT_MODULES_DIR}" ]; then cp -R "${SIMULATOR_SWIFT_MODULES_DIR}" "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Modules/${PROJECT_NAME}.swiftmodule" fi # 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 "${BUILD_DIR}/${CONFIGURATION}-universal"