¿Cuál es la diferencia entre #import y #include en Objective-C?

¿Cuáles son las diferencias entre #import y #include en Objective-C y hay momentos en los que debe usar uno sobre el otro? ¿Está desaprobado uno?

Estaba leyendo el siguiente tutorial: http://www.otierney.net/objective-c.html#preamble y su párrafo sobre #import y #include parece contradecirse a sí mismo o al menos no está claro.

La directiva #import se agregó a Objective-C como una versión mejorada de #include. Sin embargo, si mejora o no, todavía es un tema de debate. #import asegura que un archivo solo se incluya una vez para que nunca tenga un problema con los recursivos. Sin embargo, la mayoría de los archivos de cabecera decentes se protegen contra esto de todos modos, por lo que no es realmente un gran beneficio.

Básicamente, depende de usted decidir cuál quiere usar. Tiendo a Importar encabezados para elementos de Objective-C (como las definiciones de clase y demás) y #incluir cosas C estándar que necesito. Por ejemplo, uno de mis archivos fuente podría verse así:

#import  #include  #include  

Parece haber mucha confusión con respecto al preprocesador.

Lo que hace el comstackdor cuando ve un #include que reemplaza esa línea con el contenido de los archivos incluidos, sin hacer preguntas.

Entonces, si tienes un archivo ah con este contenido:

 typedef int my_number; 

y un archivo bc con este contenido:

 #include "ah" #include "ah" 

el archivo bc será traducido por el preprocesador antes de la comstackción para

 typedef int my_number; typedef int my_number; 

lo que dará como resultado un error de comstackción, ya que el tipo my_number se define dos veces. Aunque la definición es la misma, el lenguaje C no lo permite.

Como un encabezado a menudo se usa en más de un lugar, los protectores generalmente se usan en C. Esto se ve así:

  #ifndef _a_h_included_ #define _a_h_included_ typedef int my_number; #endif 

El archivo bc aún tendría todo el contenido del encabezado en él dos veces después de ser preprocesado. Pero la segunda instancia sería ignorada ya que la macro _a_h_included_ ya se habría definido.

Esto funciona realmente bien, pero tiene dos inconvenientes. En primer lugar, las guardias de inclusión deben escribirse, y el nombre de la macro debe ser diferente en cada encabezado. Y en segundo lugar, el comstackdor aún tiene que buscar el archivo de encabezado y leerlo tan a menudo como esté incluido.

Objective-C tiene la instrucción de preprocesador #import (también se puede usar para códigos C y C ++ con algunos comstackdores y opciones). Esto hace casi lo mismo que #include , pero también indica internamente qué archivo ya se ha incluido. La línea #import solo se reemplaza por el contenido del archivo nombrado por primera vez. Cada vez después de eso, simplemente se ignora.

Estoy de acuerdo con Jason.

Me pillaron haciendo esto:

 #import  // to use gettimeofday() function #import  // to use time() function 

Para GNU gcc, seguía quejándose de que la función time () no estaba definida.

Entonces cambié #import a #include y todo salió bien.

Razón:

Usted #import :
incluye solo una parte de usando #defines

Usted # import :
No vayas. Aunque solo parte de ya estaba incluida, como
Por lo que respecta a #import, ese archivo ya está completamente incluido.

Línea de fondo:

Los encabezados C / C ++ tradicionalmente incluyen partes de otros archivos de inclusión.
Entonces, para los encabezados C / C ++, use #include.
Para los encabezados objc / objc ++, use #import.

#include funciona igual que C #include .

#import realiza un seguimiento de qué encabezados ya se han incluido y se ignora si un encabezado se importa más de una vez en una unidad de comstackción. Esto hace innecesario usar protectores de cabecera.

El resultado final es solo usar #import en Objective-C y no te preocupes si tus encabezados terminan importando algo más de una vez.

Sé que este hilo es viejo … pero en “tiempos modernos” … existe una “estrategia de inclusión” muy superior a través de los módulos @import de clang, que a menudo se pasa por alto.

Los módulos mejoran el acceso a la API de las bibliotecas de software al reemplazar el modelo textual de inclusión de preprocesadores con un modelo semántico más robusto y más eficiente. Desde la perspectiva del usuario, el código se ve ligeramente diferente, porque uno usa una statement de importación en lugar de una directiva de preprocesador #include:

 @import Darwin; // Like including all of /usr/include. @see /usr/include/module.map 

o

 @import Foundation; // Like #import  @import ObjectiveC; // Like #import  

Sin embargo, esta importación del módulo se comporta de forma bastante diferente al #include correspondiente: cuando el comstackdor ve la importación del módulo anterior, carga una representación binaria del módulo y pone su API a disposición de la aplicación directamente. Las definiciones de preprocesador que preceden a la statement de importación no tienen ningún impacto en la API proporcionada … porque el módulo en sí se compiló como un módulo separado e independiente. Además, cualquier indicador de enlazador requerido para usar el módulo se proporcionará automáticamente cuando se importe el módulo. Este modelo de importación semántica aborda muchos de los problemas del modelo de inclusión del preprocesador.

Para habilitar módulos, pase el indicador de línea de comandos -fmodules aka CLANG_ENABLE_MODULES en Xcode – en tiempo de comstackción. Como se mencionó anteriormente, esta estrategia obvia CUALQUIER y TODOS los LDFLAGS . Al igual que en, puede ELIMINAR cualquier configuración de “OTHER_LDFLAGS”, así como las fases de “Vinculación”.

enter image description here

Creo que los tiempos de comstackción / lanzamiento para “sentir” mucho más ágil (o posiblemente, hay un retraso menor al “enlazar”?) … y también ofrecen una gran oportunidad para purgar el ahora extraño archivo Project-Prefix.pch, y la configuración de comstackción correspondiente, GCC_INCREASE_PRECOMPILED_HEADER_SHARING , GCC_PRECOMPILE_PREFIX_HEADER y GCC_PREFIX_HEADER , etc.

Además, aunque no está bien documentado … Puede crear module.map s para sus propios frameworks e incluirlos de la misma manera conveniente. Puedes echar un vistazo a mi ObjC-Clang-Modules github repo para ver algunos ejemplos de cómo implementar tales milagros.

Si está familiarizado con C ++ y macros, entonces

 #import "Class.h" 

es parecido a

 { #pragma once #include "class.h" } 

lo que significa que su clase se cargará solo una vez cuando se ejecute su aplicación.

SI #incluye un archivo dos veces en archivos .h, el comstackdor dará un error. Pero si importa un archivo más de una vez, el comstackdor lo ignorará.

En el caso de que tuviera una variable global en uno de mis archivos .h que causaba el problema, lo resolví añadiendo extern al frente.

#include solía obtener “cosas” de otro archivo a la que se usa #include . Ejemplo:

en archivo: main.cpp

 #include "otherfile.h" // some stuff here using otherfile.h objects, // functions or classes declared inside 

El protector de encabezado se usa en la parte superior de cada archivo de encabezado (* .h) para evitar incluir el mismo archivo más de una vez (si ocurre, obtendrá errores de comstackción).

en el archivo: otherfile.h

 #ifndef OTHERFILE #define OTHERFILE // declare functions, classes or objects here #endif 

incluso si pone #include “otherfile.h” n vez en su código, este dentro de él no se volverá a declarar.