@import vs #import - iOS 7

432

Ich spiele mit einigen der neuen iOS 7-Funktionen herum und arbeite mit einigen der Bildeffekte, wie im WWDC-Video "Implementing Engaging UI on iOS" beschrieben. Um einen Unschärfeeffekt innerhalb des Quellcodes für die Sitzung zu erzeugen, UIImagewurde über eine Kategorie erweitert, die UIKit wie folgt importiert:

@import UIKit;

Ich glaube, ich habe in einem anderen Sitzungsvideo etwas darüber gesehen, aber ich habe Probleme, es zu finden. Ich suche nach Hintergrundinformationen darüber, wann ich diese verwenden soll. Kann es nur mit Apple Frameworks verwendet werden? Reichen die Vorteile dieser Compiler-Direktive aus, um alten Code zu aktualisieren?

jamdaddy25
quelle

Antworten:

838

Es ist eine neue Funktion namens Module oder "semantischer Import". Weitere Informationen finden Sie in den WWDC 2013- Videos für Sitzung 205 und 404 . Es ist eine Art bessere Implementierung der vorkompilierten Header. Sie können Module mit jedem System-Framework in iOS 7 und Mavericks verwenden. Module sind eine Zusammenstellung der ausführbaren Framework-Datei und ihrer Header und werden als sicherer und effizienter als angepriesen #import.

Einer der großen Vorteile der Verwendung @importbesteht darin, dass Sie das Framework nicht in den Projekteinstellungen hinzufügen müssen, sondern automatisch . Das bedeutet, dass Sie den Schritt überspringen können, in dem Sie auf die Plus-Schaltfläche klicken, nach dem Framework suchen (goldene Toolbox) und es dann in die Gruppe "Frameworks" verschieben. Es wird viele Entwickler vor den kryptischen "Linker-Fehler" -Nachrichten bewahren.

Sie müssen das @importSchlüsselwort nicht verwenden. Wenn Sie sich für die Verwendung von Modulen entscheiden, werden alle #importund #includeDirektiven so zugeordnet, dass sie @importautomatisch verwendet werden. Das bedeutet, dass Sie Ihren Quellcode (oder den Quellcode von Bibliotheken, die Sie von einer anderen Stelle herunterladen) nicht ändern müssen. Angeblich verbessert die Verwendung von Modulen auch die Build-Leistung, insbesondere wenn Sie PCHs nicht gut verwendet haben oder wenn Ihr Projekt viele kleine Quelldateien enthält.

Module sind für die meisten Apple-Frameworks (UIKit, MapKit, GameKit usw.) vorgefertigt. Sie können sie mit selbst erstellten Frameworks verwenden: Sie werden automatisch erstellt, wenn Sie ein Swift-Framework in Xcode erstellen, und Sie können manuell eine ".modulemap" -Datei für jede Apple- oder Drittanbieter-Bibliothek erstellen .

Sie können die Code-Vervollständigung verwenden, um die Liste der verfügbaren Frameworks anzuzeigen:

Geben Sie hier die Bildbeschreibung ein

Module sind in neuen Projekten in Xcode 5 standardmäßig aktiviert . Um sie in einem älteren Projekt zu aktivieren, gehen Sie in Ihre Projekterstellungseinstellungen, suchen Sie nach "Modules" und setzen Sie "Enable Modules" auf "YES". Die "Link Frameworks" sollten auch "JA" sein:

Sie müssen Xcode 5 und das iOS 7 oder Mavericks SDK verwenden, können es jedoch weiterhin für ältere Betriebssysteme freigeben (z. B. iOS 4.3 oder was auch immer). Module ändern weder die Art und Weise, wie Ihr Code erstellt wird, noch den Quellcode.


Aus den WWDC-Folien:

  • Importiert eine vollständige semantische Beschreibung eines Frameworks
  • Muss die Header nicht analysieren
  • Besserer Weg, um die Oberfläche eines Frameworks zu importieren
  • Lädt die binäre Darstellung
  • Flexibler als vorkompilierte Header
  • Immun gegen Auswirkungen von lokalen Makrodefinitionen (zB #define readonly 0x01)
  • Standardmäßig für neue Projekte aktiviert

So verwenden Sie Module explizit:

Ersetzen #import <Cocoa/Cocoa.h>durch@import Cocoa;

Sie können auch nur einen Header mit dieser Notation importieren:

@import iAd.ADBannerView;

Die Submodule werden in Xcode automatisch für Sie vervollständigt.

Nevan König
quelle
15
@ DaveDeLong & Klaas: Danke! Ich muss zugeben, dass ich nichts über Module wusste, als ich dies zum ersten Mal beantwortete. Ich habe mir Session 404 angesehen, um es zu lernen. Die Präsentation, die Doug Gregor (der LLVM-Typ) hielt, war wirklich gut gemacht. Es gibt auch einen Vortrag über C ++ - Module, in dem die Vorteile hier erklärt werden: youtube.com/watch?v=4Xo9iH5VLQ0
Nevan King
3
@ nevan-- danke für die antwort. Ich wollte nur hinzufügen, dass Module derzeit noch keine Drittanbieter und Ihre eigenen Frameworks unterstützen.
Jamdaddy25
Können Sie dies für Ihren eigenen Unterricht verwenden?
cfischer
5
Ich denke, Sie sollten in der Lage sein, Frameworks von Drittanbietern zu importieren, wenn eine entsprechende module.map bereitgestellt wird. Die Dokumentation zum LLVM-Clang-Modul: clang.llvm.org/docs/Modules.html#module-map-language
bames53
1
Oh, eigentlich sieht es so aus, als hätte es @import sqlite3für mich funktioniert, weil ich meine eigene module.map dafür erstellt hatte und als ich feststellte, dass sqlite in OS X enthalten war und meine module.map entfernte, verwendete der Compiler weiterhin das veraltete Modul.
Bames53
46

Schöne Antwort finden Sie im Buch Learning Cocoa with Objective-C (ISBN: 978-1-491-90139-7)

Module sind eine neue Möglichkeit, Dateien und Bibliotheken in Ihre Projekte aufzunehmen und zu verknüpfen. Um zu verstehen, wie Module funktionieren und welche Vorteile sie haben, ist es wichtig, einen Blick auf den Verlauf von Objective-C und die # import-Anweisung zu werfen. Wenn Sie eine Datei zur Verwendung einschließen möchten, haben Sie im Allgemeinen einen Code, der folgendermaßen aussieht:

#import "someFile.h"

Oder bei Frameworks:

#import <SomeLibrary/SomeFile.h>

Da Objective-C eine Obermenge der Programmiersprache C ist, ist die Anweisung #import eine geringfügige Verfeinerung der #includeAussage von C. Die Anweisung #include ist sehr einfach. Es kopiert alles, was es in der enthaltenen Datei findet, während der Kompilierung in Ihren Code. Dies kann manchmal erhebliche Probleme verursachen. Stellen Sie sich zum Beispiel vor, Sie haben zwei Header-Dateien: SomeFileA.hund SomeFileB.h; SomeFileA.henthält SomeFileB.hund SomeFileB.henthält SomeFileA.h. Dies erzeugt eine Schleife und kann den Coimpiler verwirren. Um dies zu bewältigen, müssen C-Programmierer Schutzmaßnahmen gegen das Auftreten dieser Art von Ereignissen schreiben.

Bei der Verwendung #importmüssen Sie sich nicht um dieses Problem kümmern oder Header-Schutzfunktionen schreiben, um dies zu vermeiden. Es handelt sich jedoch #importimmer noch nur um eine verherrlichte Aktion zum Kopieren und Einfügen, die eine langsame Kompilierungszeit bei einer Vielzahl anderer kleinerer, aber immer noch sehr gefährlicher Probleme verursacht (z. B. eine enthaltene Datei, die etwas überschreibt, das Sie an anderer Stelle in Ihrem eigenen Code deklariert haben).

Module sind ein Versuch, dies zu umgehen. Sie sind nicht länger ein Kopieren und Einfügen in den Quellcode, sondern eine serialisierte Darstellung der enthaltenen Dateien, die nur dann in Ihren Quellcode importiert werden können, wenn und wo sie benötigt werden. Durch die Verwendung von Modulen wird Code im Allgemeinen schneller kompiliert und ist sicherer als die Verwendung von #include oder #import.

Zurück zum vorherigen Beispiel für den Import eines Frameworks:

#import <SomeLibrary/SomeFile.h>

Um diese Bibliothek als Modul zu importieren, wird der Code wie folgt geändert:

@import SomeLibrary;

Dies hat den zusätzlichen Vorteil, dass Xcode das SomeLibrary-Framework automatisch mit dem Projekt verknüpft. Mit Modulen können Sie auch nur die Komponenten, die Sie wirklich benötigen, in Ihr Projekt einbeziehen. Wenn Sie beispielsweise die AwesomeObject-Komponente im AwesomeLibrary-Framework verwenden möchten, müssen Sie normalerweise alles importieren, um nur das eine Stück zu verwenden. Mithilfe von Modulen können Sie jedoch nur das spezifische Objekt importieren, das Sie verwenden möchten:

@import AwesomeLibrary.AwesomeObject;

Für alle neuen Projekte in Xcode 5 sind Module standardmäßig aktiviert. Wenn Sie Module in älteren Projekten verwenden möchten (und dies sollten Sie auch tun), müssen diese in den Build-Einstellungen des Projekts aktiviert sein. Sobald Sie dies getan haben, können Sie beide #importund @importAnweisungen in Ihrem Code ohne Bedenken zusammen verwenden.

gbk
quelle
In meinem Projekt (Xcode 6) gibt es keine Option, die ich zum ersten Mal mit Xcode 4 gestartet habe, um Module zu aktivieren. Kann ich es irgendwie manuell hinzufügen?
Super-o
Build-Ziel ist iOS 6, ich denke, das ist das Problem
Awesome-o
4

Es funktioniert derzeit nur für die eingebauten System-Frameworks. Wenn Sie #importwie Apple verwenden, importieren Sie das UIKitFramework weiterhin in den App-Delegaten. Es wird ersetzt (wenn Module aktiviert sind und als System-Framework erkannt werden), und der Compiler ordnet es als Modulimport und nicht als Import der Header-Dateien zu . Das Verlassen des #importwird also genauso sein wie das Konvertieren in einen Modulimport, wo immer dies möglich ist

RyanTCB
quelle
2

Es scheint, dass seit XCode 7.x viele Warnungen ausgegeben werden, wenn das Clang-Modul mit aktiviert wird CLANG_ENABLE_MODULES

Sehen Sie sich viele Warnungen an, wenn Sie mit Xcode 7 mit Bibliotheken von Drittanbietern erstellen

loretoparisi
quelle
Ja, auch ich habe dieses Problem, aber wenn Sie es auf NEIN setzen, werden alle Warnungen entfernt. Wird es einen Nebeneffekt geben, wenn ich das mache?
Satheeshwaran
1

Die Verwendung von Modulen bietet einige Vorteile. Sie können es nur mit Apples Framework verwenden, es sei denn, die Modulzuordnung wird erstellt. @importist ein bisschen ähnlich wie das Vorkompilieren von Header-Dateien, wenn sie zu einer .pchDatei hinzugefügt werden. Dies ist eine Möglichkeit, den Kompilierungsprozess in der App zu optimieren. Außerdem müssen Sie keine Bibliotheken auf die alte Weise hinzufügen, da die Verwendung @importin der Tat viel schneller und effizienter ist. Wenn Sie immer noch nach einer schönen Referenz suchen, empfehle ich Ihnen dringend, diesen Artikel zu lesen .

Julian Król
quelle
0

Geschichte:

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

#include vs #import
.pch - Vorkompilierter Header

Modul - @import

Product Name == Product Module Name 

@moduleErklärung sagt Compiler eine laden vorkompilierte Binary von Rahmen , die ein Gebäude der Zeit abnehmen . Modular Framework enthält .modulemap[Info]

Wenn die Modulfunktion im Xcode-Projekt aktiviert ist #includeund #importDirektiven automatisch in diese konvertiert werden @import, ergeben sich alle Vorteile

Geben Sie hier die Bildbeschreibung ein

yoAlex5
quelle