@import vs #import - iOS 7

432

Je joue avec certaines des nouvelles fonctionnalités d'iOS 7 et travaille avec certains des effets d'image comme discuté dans la vidéo WWDC "Implémentation de l'interface utilisateur engageante sur iOS". Pour produire un effet de flou dans le code source de la session, a UIImageété étendu via une catégorie qui importe UIKit comme suit:

@import UIKit;

Je pense que j'ai vu quelque chose à ce sujet dans une autre vidéo de session, mais j'ai du mal à le trouver. Je recherche des informations générales sur le moment de l'utiliser. Peut-il uniquement être utilisé avec les frameworks Apple? Les avantages de l'utilisation de cette directive de compilation sont-ils suffisants pour que je retourne et mette à jour l'ancien code?

jamdaddy25
la source

Réponses:

838

C'est une nouvelle fonctionnalité appelée Modules ou "importation sémantique". Il y a plus d'informations dans les vidéos WWDC 2013 pour les sessions 205 et 404 . C'est une sorte de meilleure implémentation des en-têtes précompilés. Vous pouvez utiliser des modules avec n'importe quelle infrastructure système dans iOS 7 et Mavericks. Les modules sont un ensemble regroupant l'exécutable du cadre et ses en-têtes et sont présentés comme étant plus sûrs et plus efficaces que #import.

L'un des grands avantages de l'utilisation @importest que vous n'avez pas besoin d'ajouter le framework dans les paramètres du projet, cela se fait automatiquement . Cela signifie que vous pouvez ignorer l'étape où vous cliquez sur le bouton plus et rechercher le cadre (boîte à outils dorée), puis le déplacer vers le groupe "Frameworks". Il sauvera de nombreux développeurs des messages cryptiques "Linker error".

Vous n'avez pas vraiment besoin d'utiliser le @importmot - clé. Si vous choisissez d'utiliser des modules, toutes les directives #importet #includesont mappées pour être utilisées @importautomatiquement. Cela signifie que vous n'avez pas à modifier votre code source (ou le code source des bibliothèques que vous téléchargez ailleurs). Censément, l'utilisation de modules améliore également les performances de construction, surtout si vous n'avez pas bien utilisé les PCH ou si votre projet contient de nombreux petits fichiers source.

Les modules sont pré-construits pour la plupart des frameworks Apple (UIKit, MapKit, GameKit, etc.). Vous pouvez les utiliser avec des frameworks que vous créez vous-même: ils sont créés automatiquement si vous créez un framework Swift dans Xcode, et vous pouvez créer manuellement un fichier ".modulemap" vous-même pour n'importe quelle bibliothèque Apple ou tierce .

Vous pouvez utiliser la complétion de code pour voir la liste des frameworks disponibles:

entrez la description de l'image ici

Les modules sont activés par défaut dans les nouveaux projets dans Xcode 5 . Pour les activer dans un projet plus ancien, allez dans les paramètres de construction de votre projet, recherchez "Modules" et réglez "Activer les modules" sur "OUI". Les "cadres de lien" doivent également être "OUI":

Vous devez utiliser Xcode 5 et le SDK iOS 7 ou Mavericks, mais vous pouvez toujours publier pour les anciens systèmes d'exploitation (par exemple iOS 4.3 ou autre). Les modules ne changent pas la façon dont votre code est construit ou le code source.


Des diapositives de la WWDC:

  • Importe la description sémantique complète d'un framework
  • N'a pas besoin d'analyser les en-têtes
  • Meilleure façon d'importer l'interface d'un framework
  • Charge la représentation binaire
  • Plus flexible que les en-têtes précompilés
  • Insensible aux effets des définitions de macro locales (par exemple #define readonly 0x01)
  • Activé pour les nouveaux projets par défaut

Pour utiliser explicitement des modules:

Remplacez #import <Cocoa/Cocoa.h>par@import Cocoa;

Vous pouvez également importer un seul en-tête avec cette notation:

@import iAd.ADBannerView;

Les sous-modules se complètent automatiquement pour vous dans Xcode.

nevan king
la source
15
@DaveDeLong & Klaas: Merci! Je dois admettre que je ne connaissais rien aux modules lorsque j'ai répondu pour la première fois. Je suis allé voir la session 404 pour l'apprendre. La présentation donnée par Doug Gregor (le gars du LLVM) était vraiment bien faite. Il y a aussi une conférence sur les modules C ++ où explique les avantages ici: youtube.com/watch?v=4Xo9iH5VLQ0
nevan king
3
@ nevan-- merci pour la réponse. Je voulais juste ajouter que les modules ne prennent pas encore en charge les logiciels tiers et vos propres frameworks.
jamdaddy25
Pouvez-vous l'utiliser pour vos propres cours?
cfischer
5
Je pense que vous devriez pouvoir @importer des frameworks tiers si un module.map approprié est fourni. La documentation du module LLVM clang: clang.llvm.org/docs/Modules.html#module-map-language
bames53
1
Oh, en fait, cela semble avoir @import sqlite3fonctionné pour moi parce que j'avais créé mon propre module.map pour cela et quand j'ai réalisé que sqlite était inclus dans OS X et supprimé mon module.map, le compilateur a continué à utiliser le module périmé.
bames53
46

Belle réponse que vous pouvez trouver dans le livre Learning Cocoa with Objective-C (ISBN: 978-1-491-90139-7)

Les modules sont un nouveau moyen d'inclure et de lier des fichiers et des bibliothèques dans vos projets. Pour comprendre le fonctionnement des modules et leurs avantages, il est important de revenir sur l'historique d'Objective-C et sur l'instruction #import. Chaque fois que vous souhaitez inclure un fichier à utiliser, vous aurez généralement du code qui ressemble à ceci:

#import "someFile.h"

Ou dans le cas des frameworks:

#import <SomeLibrary/SomeFile.h>

Parce que Objective-C est un sur-ensemble du langage de programmation C, la déclaration #import est un raffinement mineur de la #includedéclaration de C. L'instruction #include est très simple; il copie tout ce qu'il trouve dans le fichier inclus dans votre code lors de la compilation. Cela peut parfois provoquer des problèmes importants. Par exemple, imaginez que vous avez deux fichiers d'en-tête: SomeFileA.het SomeFileB.h; SomeFileA.hcomprend SomeFileB.h, et SomeFileB.hcomprend SomeFileA.h. Cela crée une boucle et peut confondre le coimpilateur. Pour y faire face, les programmeurs C doivent écrire des protections contre ce type d'événement.

Lors de l'utilisation #import, vous n'avez pas à vous soucier de ce problème ou à écrire des protections d'en-tête pour l'éviter. Cependant, ce #importn'est encore qu'une action de copier-coller glorifiée, ce qui ralentit le temps de compilation parmi une foule d'autres problèmes plus petits mais toujours très dangereux (comme un fichier inclus remplaçant quelque chose que vous avez déclaré ailleurs dans votre propre code.)

Les modules tentent de contourner ce problème. Ils ne sont plus un copier-coller dans le code source, mais une représentation sérialisée des fichiers inclus qui peuvent être importés dans votre code source uniquement quand et où ils sont nécessaires. En utilisant des modules, le code se compilera généralement plus rapidement et sera plus sûr que d'utiliser #include ou #import.

Revenons à l'exemple précédent d'importation d'un framework:

#import <SomeLibrary/SomeFile.h>

Pour importer cette bibliothèque en tant que module, le code serait changé en:

@import SomeLibrary;

Cela a l'avantage supplémentaire de Xcode reliant automatiquement le framework SomeLibrary au projet. Les modules vous permettent également d'inclure uniquement les composants dont vous avez vraiment besoin dans votre projet. Par exemple, si vous souhaitez utiliser le composant AwesomeObject dans le cadre AwesomeLibrary, vous devrez normalement tout importer juste pour utiliser la pièce unique. Cependant, à l'aide de modules, vous pouvez simplement importer l'objet spécifique que vous souhaitez utiliser:

@import AwesomeLibrary.AwesomeObject;

Pour tous les nouveaux projets réalisés dans Xcode 5, les modules sont activés par défaut. Si vous souhaitez utiliser des modules dans des projets plus anciens (et vous devriez vraiment le faire), ils devront être activés dans les paramètres de construction du projet. Une fois que vous avez fait cela, vous pouvez utiliser à la fois les instructions #importet @importdans votre code sans aucun problème.

gbk
la source
Il n'y a pas d'option dans mon projet (Xcode 6) que j'ai commencé sur Xcode 4 pour activer les modules. Puis-je l'ajouter manuellement d'une manière ou d'une autre?
Awesome-o
La cible de construction est iOS 6, je pense que c'est le problème
Awesome-o
4

Il ne fonctionne actuellement que pour les cadres système intégrés. Si vous utilisez #importcomme Apple, importez toujours le UIKitframework dans le délégué de l'application, il est remplacé (si les modules sont activés et reconnus comme framework système) et le compilateur le remappera pour être une importation de module et non une importation des fichiers d'en-tête de toute façon . Donc, laisser le #importsera le même que celui converti en importation de module si possible de toute façon

RyanTCB
la source
1

Il y a quelques avantages à utiliser des modules. Vous ne pouvez l'utiliser qu'avec le framework Apple à moins que la carte de module ne soit créée. @importest un peu similaire à la pré-compilation des fichiers d'en-têtes lorsqu'ils sont ajoutés au .pchfichier, ce qui permet d'ajuster l'application le processus de compilation. De plus, vous n'avez pas besoin d'ajouter des bibliothèques à l'ancienne, l'utilisation @importest en fait beaucoup plus rapide et efficace. Si vous cherchez toujours une belle référence, je vous recommande fortement de lire cet article .

Julian Król
la source
0

Histoire:

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

#include vs #import
.pch - En-tête précompilé

Module - @import

Product Name == Product Module Name 

@moduleLa déclaration dit au compilateur de charger un binaire de framework précompilé qui diminue le temps de construction . Le cadre modulaire contient .modulemap[À propos]

Si la fonctionnalité du module est activée dans le projet Xcode #includeet les #importdirectives sont automatiquement converties en ce @importqui apporte tous les avantages

entrez la description de l'image ici

yoAlex5
la source