@import vs #import - iOS 7

432

Estou brincando com alguns dos novos recursos do iOS 7 e trabalhando com alguns dos Efeitos de imagem, conforme discutido no vídeo da WWDC "Implementando a interface do usuário envolvente no iOS". Para produzir um efeito de desfoque no código fonte da sessão, UIImagefoi estendido por meio de uma categoria que importa o UIKit da seguinte forma:

@import UIKit;

Acho que vi algo sobre isso em outro vídeo da sessão, mas estou tendo problemas para encontrá-lo. Estou procurando informações sobre quando usar isso. Só pode ser usado com estruturas da Apple? Os benefícios de usar essa diretiva de compilador são suficientes para eu voltar e atualizar o código antigo?

jamdaddy25
fonte

Respostas:

838

É um novo recurso chamado Módulos ou "importação semântica". Há mais informações nos vídeos da WWDC 2013 para as sessões 205 e 404 . É uma espécie de melhor implementação dos cabeçalhos pré-compilados. Você pode usar módulos com qualquer uma das estruturas do sistema no iOS 7 e no Mavericks. Os módulos são um empacotamento junto do executável da estrutura e seus cabeçalhos e são apontados como mais seguros e eficientes do que #import.

Uma das grandes vantagens do uso @importé que você não precisa adicionar a estrutura nas configurações do projeto, isso é feito automaticamente . Isso significa que você pode pular a etapa em que clica no botão de adição e procurar a estrutura (caixa de ferramentas dourada) e movê-la para o grupo "Estruturas". Ele salvará muitos desenvolvedores das mensagens enigmáticas "Erro do vinculador".

Na verdade, você não precisa usar a @importpalavra - chave. Se você optar por usar os módulos, todas as diretivas #importe #includeserão mapeadas para uso @importautomático. Isso significa que você não precisa alterar seu código-fonte (ou o código-fonte das bibliotecas que você baixa de outro local). Supostamente, o uso de módulos também melhora o desempenho da compilação, especialmente se você não estiver usando bem as PCHs ou se o seu projeto tiver muitos arquivos de origem pequenos.

Os módulos são pré-criados para a maioria das estruturas da Apple (UIKit, MapKit, GameKit, etc.). Você pode usá-los com estruturas criadas por você mesmo: elas são criadas automaticamente se você criar uma estrutura Swift no Xcode e criar manualmente manualmente um arquivo ".modulemap" para qualquer biblioteca da Apple ou de terceiros .

Você pode usar o preenchimento de código para ver a lista de estruturas disponíveis:

insira a descrição da imagem aqui

Os módulos são ativados por padrão em novos projetos no Xcode 5 . Para habilitá-los em um projeto mais antigo, entre nas configurações de construção do seu projeto, pesquise "Módulos" e defina "Ativar Módulos" como "SIM". Os "Link Frameworks" também devem ser "YES":

É necessário usar o Xcode 5 e o iOS 7 ou o Mavericks SDK, mas ainda é possível lançar para sistemas operacionais mais antigos (por exemplo, iOS 4.3 ou o que for). Os módulos não alteram a forma como seu código é criado ou o código fonte.


Nos slides da WWDC:

  • Importa a descrição semântica completa de uma estrutura
  • Não precisa analisar os cabeçalhos
  • Melhor maneira de importar a interface de uma estrutura
  • Carrega representação binária
  • Mais flexível do que cabeçalhos pré-compilados
  • Imune a efeitos de definições de macro locais (por exemplo #define readonly 0x01)
  • Ativado para novos projetos por padrão

Para usar explicitamente os módulos:

Substitua #import <Cocoa/Cocoa.h>por@import Cocoa;

Você também pode importar apenas um cabeçalho com esta notação:

@import iAd.ADBannerView;

Os submódulos são preenchidos automaticamente para você no Xcode.

rei nevan
fonte
15
@DaveDeLong & Klaas: Obrigado! Devo admitir que não sabia nada sobre módulos quando respondi pela primeira vez. Eu assisti a Sessão 404 para aprender. A apresentação que Doug Gregor (o LLVM) fez foi muito bem feita. Há também uma palestra C ++ módulos onde explica as vantagens aqui: youtube.com/watch?v=4Xo9iH5VLQ0
rei Nevan
3
@ nevan-- obrigado pela resposta. Eu só queria acrescentar que os módulos ainda não suportam terceiros e suas próprias estruturas.
jamdaddy25
Você pode usar isso para suas próprias aulas?
cfischer
5
Eu acho que você deve conseguir importar estruturas de terceiros se for fornecido um module.map apropriado. A documentação do módulo clang LLVM: clang.llvm.org/docs/Modules.html#module-map-language
bames53
1
Ah, na verdade, parece que @import sqlite3funcionou para mim porque eu criei meu próprio module.map para ele e quando percebi que o sqlite foi incluído no OS X e removi o module.map, o compilador continuou usando o módulo obsoleto.
usar o seguinte comando
46

Boa resposta que você pode encontrar no livro Learning Cocoa with Objective-C (ISBN: 978-1-491-90139-7)

Os módulos são um novo meio de incluir e vincular arquivos e bibliotecas em seus projetos. Para entender como os módulos funcionam e quais benefícios eles têm, é importante relembrar o histórico do Objective-C e a instrução #import Sempre que você desejar incluir um arquivo para uso, geralmente haverá um código semelhante a este:

#import "someFile.h"

Ou no caso de frameworks:

#import <SomeLibrary/SomeFile.h>

Como o Objective-C é um superconjunto da linguagem de programação C, a declaração #import é um refinamento menor na #includedeclaração de C. A instrução #include é muito simples; copia tudo o que encontra no arquivo incluído no seu código durante a compilação. Às vezes, isso pode causar problemas significativos. Por exemplo, imagine que você tenha dois arquivos de cabeçalho: SomeFileA.he SomeFileB.h; SomeFileA.hinclui SomeFileB.he SomeFileB.hinclui SomeFileA.h. Isso cria um loop e pode confundir o coimpiler. Para lidar com isso, os programadores C precisam escrever proteções contra esse tipo de evento.

Ao usar #import, você não precisa se preocupar com esse problema ou escrever protetores de cabeçalho para evitá-lo. No entanto, #importainda é apenas uma ação gloriosa de copiar e colar, causando um tempo de compilação lento entre uma série de outros problemas menores, mas ainda muito perigosos (como um arquivo incluído substituindo algo que você declarou em outro lugar no seu próprio código).

Módulos são uma tentativa de contornar isso. Eles não são mais um copiar e colar no código fonte, mas uma representação serializada dos arquivos incluídos que podem ser importados para o código-fonte somente quando e onde forem necessários. Usando módulos, o código geralmente compila mais rápido e é mais seguro do que usar #include ou #import.

Retornando ao exemplo anterior de importação de uma estrutura:

#import <SomeLibrary/SomeFile.h>

Para importar esta biblioteca como um módulo, o código seria alterado para:

@import SomeLibrary;

Isso tem o bônus adicional do Xcode vinculando a estrutura SomeLibrary ao projeto automaticamente. Os módulos também permitem incluir apenas os componentes que você realmente precisa em seu projeto. Por exemplo, se você quiser usar o componente AwesomeObject na estrutura AwesomeLibrary, normalmente precisará importar tudo apenas para usar a peça única. No entanto, usando módulos, você pode apenas importar o objeto específico que deseja usar:

@import AwesomeLibrary.AwesomeObject;

Para todos os novos projetos feitos no Xcode 5, os módulos são ativados por padrão. Se você quiser usar módulos em projetos mais antigos (e realmente deve), eles deverão ser ativados nas configurações de compilação do projeto. Depois de fazer isso, você pode usar as instruções #importe @importno seu código juntas sem nenhuma preocupação.

gbk
fonte
Não há nenhuma opção no meu projeto (Xcode 6) que eu iniciei no Xcode 4 para ativar módulos. Posso adicioná-lo manualmente de alguma forma?
Impressionante-o
Destino de compilação é iOS 6, penso que esta é a questão
impressionante-o
4

Atualmente, ele funciona apenas para as estruturas de sistema integradas. Se você usar #importcomo a apple ainda importando a UIKitestrutura no delegado do aplicativo, ela será substituída (se os módulos estiverem ativados e for reconhecida como uma estrutura do sistema) e o compilador fará o remapeamento para que seja uma importação de módulo e não uma importação dos arquivos de cabeçalho de qualquer maneira . Portanto, deixar o #importserá igual ao convertido para uma importação de módulo sempre que possível

RyanTCB
fonte
2

Parece que desde o XCode 7.xa muitos avisos são lançados ao ativar o módulo clang com CLANG_ENABLE_MODULES

Dê uma olhada em muitos avisos ao criar com o Xcode 7 com bibliotecas de terceiros

Loretoparisi
fonte
Sim, também tenho esse problema, mas defini-lo como NÃO remove todos os avisos. Haverá um efeito colateral quando eu fizer isso?
Satheeshwaran
1

Existem alguns benefícios do uso de módulos. Você pode usá-lo apenas com a estrutura da Apple, a menos que o mapa do módulo seja criado. @importé um pouco semelhante à pré-compilação de arquivos de cabeçalhos quando adicionados ao .pcharquivo, que é uma maneira de ajustar o aplicativo ao processo de compilação. Além disso, você não precisa adicionar bibliotecas da maneira antiga, o uso @importé muito mais rápido e eficiente. Se você ainda procura uma boa referência, recomendo que você leia este artigo .

Julian Król
fonte
0

História:

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

#include vs #import
.pch - Cabeçalho pré-compilado

Módulo - @import

Product Name == Product Module Name 

@moduledeclaração diz ao compilador para carregar um binário pré - compilado da estrutura que diminui o tempo de construção . O Framework modular contém .modulemap[Sobre]

Se o recurso do módulo estiver ativado no projeto Xcode #includee as #importdiretivas forem convertidas automaticamente, @importisso traz todas as vantagens

insira a descrição da imagem aqui

yoAlex5
fonte