ios xcode frameworks weak-linking

ios - ¿Qué significa "debilitar" un marco?



xcode frameworks (3)

En Xcode, puedo establecer un marco en "Opcional" en lugar de "Requerido", lo que significa que el marco está débil vinculado.

¿Eso significa que el marco solo se incluye en el paquete cuando se importa en algún lugar?

Quiero enlazar de forma débil algunos marcos de depuración que utilizan API privada , y no quiero que aparezcan en la compilación de la App Store.


¿Eso significa que el marco solo se incluye en el paquete cuando se importa en algún lugar?

Esto depende de cómo configuró sus esquemas u objetivos.

Podría usar un solo esquema para la depuración e incluir su marco opcional solo allí. Utilice otro esquema sin el marco opcional para el lanzamiento.

ACTUALIZAR

Para hacer esto, base su nuevo esquema en la configuración de un proyecto y configure OTHER_LDFLAGS como se describe en la respuesta de hagi .


Encontré un enlace débil cuando estaba usando iAds. El problema fue que si vinculo fuertemente el marco iAds y ejecuto la aplicación en un dispositivo con SDK que no es compatible con iAds, simplemente se bloqueará. Enlace débil permitido para evitar los choques. Todavía creo que incluso con enlaces débiles, todavía tiene que verificar el código si el marco está disponible o no.


Nota importante : esta respuesta se escribió antes de que se anunciara iOS 8. Si bien los detalles técnicos aún se aplican a los marcos del sistema, ahora es posible crear sus propios marcos vinculados dinámicamente que se envían dentro de su paquete de aplicaciones. Existen restricciones, por ejemplo, solo una aplicación y sus extensiones pueden vincularse a la misma instancia de un marco integrado, pero el hecho es que es posible un marco personalizado, vinculado dinámicamente desde iOS 8. Si desea obtener más información, consulte esta guía. ( Uso de un marco incorporado para compartir código ) y la sesión 416 de la WWDC 2014, Creación de marcos modernos .

Respuesta original : ninguno de los marcos (de plataforma) está realmente " incluido en el paquete ". En su lugar, su aplicación tiene una referencia (" enlace ") a un marco una vez que la agrega a la fase de compilación "Enlace binario con biblioteca". Los marcos están preinstalados en los dispositivos. Cuando ejecuta una aplicación, todas las referencias del marco de la aplicación se resuelven mediante el enlazador dinámico (en el dispositivo), lo que significa que el código del marco se carga para que su aplicación pueda usarlo.

Es posible que algunos marcos no estén disponibles en todos los dispositivos que pretende admitir, por ejemplo, PassKit se introdujo en iOS 6. Si ejecuta una aplicación que se vincula con PassKit en un dispositivo con iOS 5, se bloquea justo después del lanzamiento, porque el enlazador dinámico no puede Encuentra el marco en el dispositivo. Sin embargo, si realiza un enlace débil de PassKit, el enlazador dinámico establecerá todos los símbolos del marco en nil , si no se puede encontrar el marco. Esto evita que la aplicación se bloquee y puede verificar la disponibilidad de los símbolos en tiempo de ejecución, por ejemplo:

if ([PKPass class]) { // Class is available - use it PKPass *pass = [[PKPass alloc] init]; }

[PKPass class] es segura de usar en todos los dispositivos / sistemas ya que el símbolo de la clase PKPass será nil en sistemas antiguos, y la mensajería nil no es un problema en Objective-C.

Más sobre enlaces débiles: documentación de Apple

Para realmente responder a su pregunta:

¿Eso significa que el marco solo se incluye en el paquete cuando se importa en algún lugar?

No. El marco siempre estará vinculado desde la aplicación. Solo cuando el marco no se encuentra en el dispositivo real en el que se está ejecutando la aplicación, el marco no se cargará.

Una solución sería tener objetivos separados para las configuraciones de Depuración y App Store. Una alternativa es no utilizar la fase de compilación incorporada "Vincular binario con biblioteca" de Xcode, sino vincular los marcos de depuración a través de opciones de vinculador. Estos se pueden especificar para cada configuración (Debug / Release / ...) por separado, así:

Si quieres vincularlo débilmente, usa -weak_framework PassKit (PassKit, por supuesto, solo es un ejemplo aquí ... inserta el nombre de tu marco). Si su marco de depuración no está en uno de los directorios del marco predeterminado, es posible que deba proporcionar una ruta completa o modificar la ruta de búsqueda de marcos. Además, probablemente debas usar macros para asegurarte de que ninguno de los códigos que utilizan los marcos de debug lo haga en la compilación de App Store.

Edición : Otra opción desde Xcode 5 es usar @import <FrameworkName>; . De esta manera, puede dejar la fase "Enlace binario ..." vacía y activar el enlace de los marcos en el código. Luego puede usar macros como DEBUG para asegurarse de que algunos marcos no se usen para las construcciones de App Store. Hay una excelente respuesta con respecto a @import .