Qual é a diferença entre #import e #include em Objective-C?

Quais são as diferenças entre #import e #include em Objective-C e há momentos em que você deve usar um sobre o outro? Está um obsoleto?

Eu estava lendo o seguinte tutorial: http://www.otierney.net/objective-c.html#preamble e seu parágrafo sobre #import e #include parece se contradizer ou pelo menos não é claro.

A diretiva #import foi adicionada ao Objective-C como uma versão aprimorada do #include. Seja ou não melhorado, no entanto, ainda é uma questão de debate. #import garante que um arquivo seja incluído apenas uma vez, para que você nunca tenha problemas com inclusões recursivas. No entanto, os arquivos de header mais decentes protegem-se contra isso de qualquer maneira, então não é realmente um grande benefício.

Basicamente, cabe a você decidir qual você quer usar. Eu tenho tendência a #importar headers para objects Objective-C (como definições de classs e coisas assim) e #include coisas padrão C que eu preciso. Por exemplo, um dos meus arquivos de origem pode ser assim:

#import  #include  #include  

Parece haver muita confusão em relação ao pré-processador.

O que o compilador faz quando vê um #include que substitui essa linha com o conteúdo dos arquivos incluídos, sem perguntas.

Então, se você tem um arquivo ah com este conteúdo:

 typedef int my_number; 

e um arquivo bc com este conteúdo:

 #include "ah" #include "ah" 

o arquivo bc será traduzido pelo pré-processador antes da compilation para

 typedef int my_number; typedef int my_number; 

o que resultará em um erro do compilador, pois o tipo my_number é definido duas vezes. Mesmo que a definição seja a mesma, isso não é permitido pela linguagem C.

Uma vez que um header geralmente é usado em mais de um local, os guardas geralmente são usados ​​em C. Isso é assim:

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

O arquivo bc ainda teria todo o conteúdo do header duas vezes depois de ser pré-processado. Mas a segunda instância seria ignorada, pois a macro _a_h_included_ já teria sido definida.

Isso funciona muito bem, mas tem dois inconvenientes. Em primeiro lugar, as proteções de inclusão devem ser escritas e o nome da macro deve ser diferente em cada header. E, em segundo lugar, o compilador ainda precisa procurar o arquivo de header e lê-lo com a mesma freqüência que é incluído.

Objective-C tem a instrução do pré-processador #import (também pode ser usada para código C e C ++ com alguns compiladores e opções). Isso faz quase o mesmo que #include , mas também observa internamente qual arquivo já foi incluído. A linha #import é substituída apenas pelo conteúdo do arquivo nomeado pela primeira vez em que é encontrado. Toda vez que depois disso é apenas ignorado.

Eu concordo com o Jason.

Eu fui pego fazendo isso:

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

Para o GNU gcc, ele ficava reclamando que a function time () não estava definida.

Então eu mudei o #import para #include e tudo correu bem.

Razão:

Você #import :
inclui apenas uma parte de

Você #import

Resumindo:

Os headers C / C ++ incluem tradicionalmente partes de outros arquivos de inclusão.
Portanto, para headers C / C ++, use #include.
Para headers objc / objc ++, use #import.

#include funciona como o C #include .

#import mantém o controle de quais headers já foram incluídos e é ignorado se um header for importado mais de uma vez em uma unidade de compilation. Isso torna desnecessário o uso de proteções de header.

A linha de fundo é apenas usar # #import em Objective-C e não se preocupe se seus headers acabam importando algo mais de uma vez.

Eu sei que esta discussão é antiga … mas em “tempos modernos” .. há um muito superior “include estratégia” através de módulos @import do clang – que é muitas vezes esquecido ..

Os módulos melhoram o access à API de bibliotecas de software, substituindo o modelo de inclusão de pré-processador textual por um modelo semântico mais robusto e eficiente. Do ponto de vista do usuário, o código parece apenas um pouco diferente, porque um usa uma declaração de importação em vez de uma diretiva de pré-processador #include:

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

ou

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

No entanto, a importação deste módulo se comporta de maneira bem diferente do #include correspondente: quando o compilador vê a importação do módulo acima, ele carrega uma representação binária do módulo e disponibiliza sua API diretamente ao aplicativo. As definições de pré-processador que precedem a declaração de importação não causam impacto na API fornecida … porque o próprio módulo foi compilado como um módulo autônomo separado. Além disso, quaisquer sinalizadores de linker necessários para usar o módulo serão fornecidos automaticamente quando o módulo for importado. Esse modelo de importação semântica aborda muitos dos problemas do modelo de inclusão do pré-processador.

Para habilitar os módulos, passe os flag-line -fmodules linha de -fmodules também conhecidos como CLANG_ENABLE_MODULES no Xcode – em tempo de compilation. Como mencionado acima, esta estratégia elimina QUALQUER e TODOS os LDFLAGS . Como em, você pode REMOVER qualquer configuração “OTHER_LDFLAGS”, assim como qualquer fase de “Vinculação”.

insira a descrição da imagem aqui

Acho que tempos de compilation / lançamento “parecem” muito mais rápidos (ou possivelmente, há apenas um atraso menor do que “vinculação”?) … e também fornece uma ótima oportunidade para limpar o agora irrelevante arquivo Project-Prefix.pch, e configurações de construção correspondentes, GCC_INCREASE_PRECOMPILED_HEADER_SHARING , GCC_PRECOMPILE_PREFIX_HEADER e GCC_PREFIX_HEADER , etc.

Além disso, embora não seja bem documentado… Você pode criar o module.map s para suas próprias estruturas e incluí-las da mesma maneira conveniente. Você pode dar uma olhada no meu repository github ObjC-Clang-Modules para alguns exemplos de como implementar esses milagres.

Se você está familiarizado com C ++ e macros, então

 #import "Class.h" 

é similar a

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

o que significa que sua class só será carregada uma vez quando seu aplicativo for executado.

Se você #include um arquivo duas vezes em arquivos .h que o compilador dará erro. Mas se você #importar um arquivo mais de uma vez, o compilador irá ignorá-lo.

Em maiúsculas, eu tinha uma variável global em um dos meus arquivos .h que estava causando o problema, e resolvi adicionando extern na frente dele.

#include ele costumava pegar “coisas” de outro arquivo para o que o #include é usado. Ex:

no arquivo: main.cpp

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

O protetor de header é usado no topo de cada arquivo de header (* .h) para evitar include o mesmo arquivo mais de uma vez (se acontecer, você receberá erros de compilation).

no arquivo: otherfile.h

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

mesmo se você colocar #include “otherfile.h” n tempo em seu código, isso não será redeclarado.