¿Cuál es la diferencia entre # importar y # incluir en Objective-C?


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

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

Author: Ryan Guill, 2009-01-13

9 answers

La directiva #import se añadió a Objective-C como una versión mejorada de #include. Si ha mejorado o no, sin embargo, sigue siendo un tema de debate. # import asegura que un archivo solo se incluya una vez para que nunca tengas un problema con las inclusiones recursivas. Sin embargo, la mayoría de los archivos de encabezado decentes se protegen contra esto de todos modos, por lo que no es realmente un gran beneficio.

Básicamente, depende de usted decidir qué desea usar. Tiendo a # importar encabezados para Objective-C things (como las definiciones de clase y tal) y # incluyen cosas estándar de C que necesito. Por ejemplo, uno de mis archivos fuente podría tener este aspecto:

#import <Foundation/Foundation.h>

#include <asl.h>
#include <mach/mach.h>
 328
Author: Jason Coco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-27 19:05:13

Parece haber mucha confusión con respecto al preprocesador.

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

Así que si tienes un archivo a.h con este contenido:

typedef int my_number;

Y un archivo b.c con este contenido:

#include "a.h"
#include "a.h"

El archivo b.c será traducido por el preprocesador antes de la compilación a

typedef int my_number;
typedef int my_number;

Que resultará en un error del compilador, ya que el tipo my_number se define dos veces. A pesar de que la definición es la misma, esto no está permitido por el lenguaje C.

Dado que un encabezado a menudo se usa en más de un lugar include guards generalmente se usan en C. Esto se ve así:

 #ifndef _a_h_included_
 #define _a_h_included_

 typedef int my_number;

 #endif

El archivo b.c todavía tendría todo el contenido de la cabecera en él dos veces después de ser preprocesado. Pero la segunda instancia sería ignorada ya que la macro _a_h_included_ ya habría sido definida.

Esto funciona realmente bueno, pero tiene dos inconvenientes. En primer lugar, los protectores include tienen que ser escritos, y el nombre de la macro tiene que ser diferente en cada encabezado. Y en segundo lugar, el compilador todavía tiene que buscar el archivo de encabezado y leerlo tan a menudo como se incluye.

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

 335
Author: Sven,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-09-17 22:38:15

Estoy de acuerdo con Jason.

Me atraparon haciendo esto:

#import <sys/time.h>  // to use gettimeofday() function
#import <time.h>      // to use time() function

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

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

Razón:

#importas :
     incluye solamente una parte de usando # define

# import :
    No vamos. Aunque solo una parte del tiempo.h > ya estaba incluido, como
    en cuanto a # import se refiere, ese archivo ahora ya está completamente incluido.

En pocas palabras:

Los encabezados C/C++ tradicionalmente incluyen partes de otros archivos include.
Así que para los encabezados C/C++, use # include.
Para las cabeceras objc/objc++, utilice # import.

 61
Author: user512705,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-11 18:49:57

#include funciona igual que el C #include.

#import realiza un seguimiento de los encabezados que ya se han incluido y se ignora si un encabezado se importa más de una vez en una unidad de compilación. Esto hace innecesario el uso de protectores de cabecera.

La conclusión es simplemente usar #import en Objective-C y no te preocupes si tus encabezados terminan importando algo más de una vez.

 22
Author: Ferruccio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-01-13 16:28:39

Sé que este hilo es viejo... pero en "tiempos modernos".. hay 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 reemplazando el modelo de inclusión de preprocesador textual por un modelo semántico más robusto y eficiente. Desde la perspectiva del usuario, el código se ve solo ligeramente diferente, porque se usa una declaración de importación en lugar de un preprocesador # include directiva:

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

O

@import Foundation;  //  Like #import <Foundation/Foundation.h>
@import ObjectiveC;  //  Like #import <objc/runtime.h>

Sin embargo, esta importación de módulos se comporta de manera bastante diferente de la correspondiente #include: cuando el compilador ve la importación de módulos anterior, carga una representación binaria del módulo y hace que su API esté disponible para la aplicación directamente. Las definiciones de preprocesador que preceden a la declaración de importación no tienen ningún impacto en la API proporcionada... porque el módulo en sí fue compilado como un módulo independiente. Además, cualquier indicador de enlace requerido para usar el módulo automáticamente se proporcionará 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 los módulos, pase la bandera de línea de comandos -fmodules aka CLANG_ENABLE_MODULES en Xcode-en tiempo de compilación. Como se mencionó anteriormente.. esta estrategia obviará TODO LDFLAGS. Al igual que en, puede eliminar cualquier configuración de "OTHER_LDFLAGS", así como cualquier " Enlace" fase..

introduzca la descripción de la imagen aquí

Encuentro que los tiempos de compilación / lanzamiento "se sienten" mucho más rápidos (o, posiblemente, hay menos retraso al "enlazar"?).. y también, proporciona una gran oportunidad para purgar el ahora extraño Proyecto-Prefijo.archivo pch y configuración de compilación correspondiente, GCC_INCREASE_PRECOMPILED_HEADER_SHARING, GCC_PRECOMPILE_PREFIX_HEADER, y GCC_PREFIX_HEADER, etc.

También, aunque no está bien documentado can puede crear module.maps para sus propios frameworks e incluirlos de la misma manera conveniente. Puedes echar un vistazo a mi ObjC-Clang-Modules github repo para algunos ejemplos de cómo implementar tales milagros.

 11
Author: Alex Gray,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-18 01:37:44

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

#import "Class.h" 

Es similar a

{
#pragma once

#include "class.h"
}

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

 3
Author: Evol Gate,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-18 13:01:22

SI #incluye un archivo dos veces .h archivos que compilador dará error. Pero si #importas un archivo más de una vez el compilador lo ignorará.

 1
Author: Husmukh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-16 09:43:02

En may case tenía una variable global en uno de mis archivos .h que estaba causando el problema, y lo resolví agregando extern delante de él.

 1
Author: Winston,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-10 15:47:32

#include solía obtener "cosas" de otro archivo al que se usa #include. Ex:

En archivo: main.cpp

#include "otherfile.h"

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

Header guard se usa en la parte superior de cada archivo de encabezado (*.h) para evitar incluir el mismo archivo más de una vez (si sucede, obtendrá errores de compilación).

En archivo: otherfile.h

#ifndef OTHERFILE
#define OTHERFILE

// declare functions, classes or objects here

#endif

Incluso si pones #include "otherfile.h" n tiempo en su código, esto dentro de no declararse.

 0
Author: Celso Dantas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-10-09 01:03:19