@import vs #import - iOS 7

432

Estoy jugando con algunas de las nuevas características de iOS 7 y trabajando con algunos de los efectos de imagen como se discute en el video de WWDC "Implementando una interfaz de usuario atractiva en iOS". Para producir un efecto de desenfoque dentro del código fuente de la sesión, UIImagese extendió a través de una categoría que importa UIKit así:

@import UIKit;

Creo que vi algo sobre esto en otro video de sesión, pero tengo problemas para encontrarlo. Estoy buscando información de fondo sobre cuándo usar esto. ¿Se puede usar solo con los marcos de Apple? ¿Son los beneficios de usar esta directiva del compilador lo suficiente como para que deba volver y actualizar el código antiguo?

jamdaddy25
fuente

Respuestas:

838

Es una nueva característica llamada Módulos o "importación semántica". Hay más información en los videos de WWDC 2013 para las sesiones 205 y 404 . Es una especie de mejor implementación de los encabezados precompilados. Puede usar módulos con cualquiera de los marcos del sistema en iOS 7 y Mavericks. Los módulos son un paquete conjunto del ejecutable del marco y sus encabezados y se promocionan como más seguros y más eficientes que #import.

Una de las grandes ventajas de usar @importes que no necesita agregar el marco en la configuración del proyecto, se hace automáticamente . Eso significa que puede omitir el paso donde hace clic en el botón más y buscar el marco (caja de herramientas dorada), luego moverlo al grupo "Marcos". Salvará a muchos desarrolladores de los crípticos mensajes de "error del vinculador".

En realidad no necesitas usar la @importpalabra clave. Si opta por usar módulos, todas las directivas #importy #includese asignan para usar @importautomáticamente. Eso significa que no tiene que cambiar su código fuente (o el código fuente de las bibliotecas que descarga desde otro lugar). Supuestamente, el uso de módulos también mejora el rendimiento de la compilación, especialmente si no ha estado usando bien PCH o si su proyecto tiene muchos archivos fuente pequeños.

Los módulos están preconstruidos para la mayoría de los frameworks de Apple (UIKit, MapKit, GameKit, etc.). Puede usarlos con marcos creados por usted mismo: se crean automáticamente si crea un marco Swift en Xcode, y puede crear manualmente un archivo ".modulemap" para cualquier biblioteca de Apple o de terceros .

Puede usar la finalización de código para ver la lista de marcos disponibles:

ingrese la descripción de la imagen aquí

Los módulos están habilitados por defecto en nuevos proyectos en Xcode 5 . Para habilitarlos en un proyecto anterior, vaya a la configuración de compilación de su proyecto, busque "Módulos" y configure "Habilitar módulos" en "SÍ". Los "marcos de enlace" también deberían ser "SÍ":

Debe usar Xcode 5 y iOS 7 o Mavericks SDK, pero aún puede lanzar para sistemas operativos más antiguos (por ejemplo, iOS 4.3 o lo que sea). Los módulos no cambian cómo se construye su código ni ninguno de los códigos fuente.


De las diapositivas de WWDC:

  • Importa una descripción semántica completa de un marco
  • No necesita analizar los encabezados
  • Mejor manera de importar la interfaz de un marco
  • Carga representación binaria
  • Más flexible que los encabezados precompilados
  • Inmune a los efectos de las macro definiciones locales (p #define readonly 0x01. Ej. )
  • Habilitado para nuevos proyectos por defecto

Para usar módulos explícitamente:

Reemplazar #import <Cocoa/Cocoa.h>con@import Cocoa;

También puede importar solo un encabezado con esta notación:

@import iAd.ADBannerView;

Los submódulos se completan automáticamente en Xcode.

nevan king
fuente
15
@DaveDeLong y Klaas: ¡Gracias! Tengo que admitir que no sabía nada sobre módulos cuando respondí esto por primera vez. Fui y vi la sesión 404 para aprenderlo. La presentación que hizo Doug Gregor (el chico de LLVM) estuvo muy bien hecha. También hay una charla sobre módulos C ++ donde explica las ventajas aquí: youtube.com/watch?v=4Xo9iH5VLQ0
nevan king
3
@ Nevan-- gracias por la respuesta. Solo quería agregar que los módulos actualmente no son compatibles con terceros y sus propios marcos.
jamdaddy25
¿Puedes usar esto para tus propias clases?
cfischer
55
Creo que debería poder importar marcos de terceros si se proporciona un module.map apropiado. La documentación del módulo clang LLVM: clang.llvm.org/docs/Modules.html#module-map-language
bames53
1
Oh, en realidad parece que @import sqlite3funcionó para mí porque había creado mi propio module.map para él y cuando me di cuenta de que sqlite estaba incluido en OS X y eliminé mi module.map, el compilador continuó usando el módulo obsoleto.
bames53
46

Buena respuesta que puedes encontrar en el libro Learning Cocoa with Objective-C (ISBN: 978-1-491-90139-7)

Los módulos son un nuevo medio para incluir y vincular archivos y bibliotecas en sus proyectos. Para comprender cómo funcionan los módulos y qué beneficios tienen, es importante revisar el historial de Objective-C y la declaración #import. Siempre que desee incluir un archivo para su uso, generalmente tendrá un código similar al siguiente:

#import "someFile.h"

O en el caso de los marcos:

#import <SomeLibrary/SomeFile.h>

Debido a que Objective-C es un superconjunto del lenguaje de programación C, la declaración #import es un refinamiento menor en la #includedeclaración de C. La declaración #include es muy simple; copia todo lo que encuentra en el archivo incluido en su código durante la compilación. Esto a veces puede causar problemas importantes. Por ejemplo, imagine que tiene dos archivos de encabezado: SomeFileA.hy SomeFileB.h; SomeFileA.hincluye SomeFileB.h, e SomeFileB.hincluye SomeFileA.h. Esto crea un bucle y puede confundir al coimpiler. Para lidiar con esto, los programadores de C tienen que escribir guardias contra este tipo de evento.

Al usarlo #import, no necesita preocuparse por este problema o escribir protectores de encabezado para evitarlo. Sin embargo, #importsigue siendo solo una acción glorificada de copiar y pegar, lo que causa un tiempo de compilación lento entre una serie de otros problemas más pequeños pero aún muy peligrosos (como un archivo incluido que anula algo que ha declarado en otro lugar en su propio código).

Los módulos son un intento de evitar esto. Ya no son una copia y pega en el código fuente, sino una representación serializada de los archivos incluidos que pueden importarse a su código fuente solo cuando y donde se necesitan. Al usar módulos, el código generalmente se compilará más rápido y será más seguro que usar #include o #import.

Volviendo al ejemplo anterior de importación de un marco:

#import <SomeLibrary/SomeFile.h>

Para importar esta biblioteca como un módulo, el código se cambiaría a:

@import SomeLibrary;

Esto tiene la ventaja adicional de que Xcode vincula el marco SomeLibrary al proyecto automáticamente. Los módulos también le permiten incluir solo los componentes que realmente necesita en su proyecto. Por ejemplo, si desea usar el componente AwesomeObject en el marco AwesomeLibrary, normalmente tendría que importar todo solo para usar la pieza única. Sin embargo, al usar módulos, puede importar el objeto específico que desea usar:

@import AwesomeLibrary.AwesomeObject;

Para todos los proyectos nuevos realizados en Xcode 5, los módulos están habilitados de forma predeterminada. Si desea utilizar módulos en proyectos más antiguos (y realmente debería hacerlo), deberá habilitarlos en la configuración de compilación del proyecto. Una vez que haga eso, puede usar ambos #importy las @importdeclaraciones en su código juntos sin ninguna preocupación.

gbk
fuente
No hay ninguna opción en mi proyecto (Xcode 6) que comencé por primera vez en Xcode 4 para habilitar módulos. ¿Puedo agregarlo manualmente de alguna manera?
Awesome-o
El objetivo de compilación es iOS 6, creo que este es el problema
Awesome-o
4

Actualmente solo funciona para los marcos de sistema integrados. Si usa #importcomo Apple todavía importa importar el UIKitmarco en el delegado de la aplicación, se reemplaza (si los módulos están encendidos y se reconoce como marco del sistema) y el compilador lo reasignará para que sea una importación de módulo y no una importación de los archivos de encabezado de todos modos . Por lo tanto, dejar el #importserá igual que su conversión a un módulo de importación donde sea posible de todos modos

RyanTCB
fuente
1

Hay algunos beneficios de usar módulos. Puede usarlo solo con el marco de Apple a menos que se cree un mapa de módulo. @importes un poco similar a los archivos de encabezados de precompilación cuando se agrega al .pcharchivo, que es una forma de ajustar el proceso de compilación de la aplicación. Además, no tiene que agregar bibliotecas a la antigua usanza, de hecho, el uso @importes mucho más rápido y eficiente. Si todavía busca una buena referencia, le recomiendo que lea este artículo .

Julian Król
fuente
0

Historia:

#include => #import => .pch => @import

#include vs #import
.pch - Encabezado precompilado

Módulo - @import

Product Name == Product Module Name 

@moduleLa declaración dice al compilador que cargue un binario precompilado de framework que disminuya el tiempo de construcción . El marco modular contiene .modulemap[Acerca de]

Si la función del módulo está habilitada en el proyecto Xcode #includey las #importdirectivas se convierten automáticamente a @importeso trae todas las ventajas

ingrese la descripción de la imagen aquí

yoAlex5
fuente