@import vs #import - iOS 7

432

Bawię się niektórymi z nowych funkcji iOS 7 i pracuję z niektórymi efektami obrazowymi, jak omówiono w filmie WWDC „Implementing Engaging UI na iOS”. Aby uzyskać efekt rozmycia w kodzie źródłowym sesji, UIImagezostał rozszerzony o kategorię, która importuje UIKit w następujący sposób:

@import UIKit;

Chyba coś o tym widziałem w innym filmie z sesji, ale mam problem ze znalezieniem tego. Szukam jakichkolwiek dodatkowych informacji o tym, kiedy tego użyć. Czy można go używać tylko z platformami Apple? Czy korzyści płynące ze stosowania tej dyrektywy kompilatora są wystarczające, że powinienem wrócić i zaktualizować stary kod?

jamdaddy25
źródło

Odpowiedzi:

838

Jest to nowa funkcja o nazwie Moduły lub „import semantyczny”. Więcej informacji znajduje się w filmach WWDC 2013 dla sesji 205 i 404 . To rodzaj lepszej implementacji wstępnie skompilowanych nagłówków. Możesz używać modułów z dowolnymi strukturami systemowymi w iOS 7 i Mavericks. Moduły stanowią razem pakiet wykonywalny frameworka i jego nagłówków i są reklamowane jako bezpieczniejsze i bardziej wydajne niż #import.

Jedną z dużych zalet używania @importjest to , że nie trzeba dodawać frameworka w ustawieniach projektu, odbywa się to automatycznie . Oznacza to, że możesz pominąć krok, w którym kliknąłeś przycisk plus i poszukać frameworka (złoty zestaw narzędzi), a następnie przenieść go do grupy „Frameworki”. Uratuje to wielu programistów przed tajemniczymi komunikatami „Błąd linkera”.

W rzeczywistości nie musisz używać @importsłowa kluczowego. Jeśli zdecydujesz się na korzystanie z modułów, wszystkie #importi wszystkie #includedyrektywy zostaną zmapowane do użycia @importautomatycznie. Oznacza to, że nie musisz zmieniać kodu źródłowego (lub kodu źródłowego bibliotek, które pobierasz z innego miejsca). Podobno użycie modułów poprawia również wydajność kompilacji, szczególnie jeśli nie korzystałeś dobrze z PCH lub jeśli twój projekt ma wiele małych plików źródłowych.

Moduły są wstępnie zbudowane dla większości platform Apple (UIKit, MapKit, GameKit itp.). Możesz ich używać z tworzonymi przez siebie szkieletami: są tworzone automatycznie, jeśli utworzysz szkielet Swift w Xcode, i możesz ręcznie samodzielnie utworzyć plik „.modulemap” dla dowolnej biblioteki Apple lub innej firmy .

Możesz użyć uzupełniania kodu, aby zobaczyć listę dostępnych frameworków:

wprowadź opis zdjęcia tutaj

Moduły są domyślnie włączone w nowych projektach w Xcode 5 . Aby włączyć je w starszym projekcie, przejdź do ustawień kompilacji projektu, wyszukaj „Moduły” i ustaw „Włącz moduły” na „TAK”. „Struktury linków” powinny być również „TAK”:

Musisz używać Xcode 5 i iOS 7 lub Mavericks SDK, ale nadal możesz wypuszczać wersje dla starszych systemów operacyjnych (powiedzmy iOS 4.3 lub cokolwiek innego). Moduły nie zmieniają sposobu budowania kodu ani żadnego kodu źródłowego.


Ze slajdów WWDC:

  • Importuje pełny opis semantyczny frameworka
  • Nie trzeba analizować nagłówków
  • Lepszy sposób na zaimportowanie interfejsu frameworka
  • Ładuje reprezentację binarną
  • Bardziej elastyczne niż wstępnie skompilowane nagłówki
  • Odporny na skutki lokalnych definicji makr (np. #define readonly 0x01)
  • Domyślnie włączony dla nowych projektów

Aby jawnie użyć modułów:

wymienić #import <Cocoa/Cocoa.h>z@import Cocoa;

Za pomocą tej notacji możesz również zaimportować tylko jeden nagłówek:

@import iAd.ADBannerView;

Podmoduły autouzupełniają się w Tobie w Xcode.

Nevan King
źródło
15
@DaveDeLong & Klaas: Dzięki! Muszę przyznać, że nie wiedziałem nic o modułach, kiedy po raz pierwszy na to odpowiedziałem. Poszedłem i oglądałem sesję 404, aby się jej nauczyć. Prezentacja, którą przedstawił Doug Gregor (facet z LLVM) była naprawdę dobrze zrobiona. Jest też dyskusja na temat modułów C ++, w której wyjaśnia zalety: youtube.com/watch?v=4Xo9iH5VLQ0
Nevan King
3
@ Nevan-- dzięki za odpowiedź. Chciałem tylko dodać, że moduły nie obsługują jeszcze zewnętrznych i własnych frameworków.
jamdaddy25
Czy możesz to wykorzystać do własnych zajęć?
cfischer,
5
Myślę, że powinieneś być w stanie @importować frameworki stron trzecich, jeśli dostarczony jest odpowiedni moduł module.map. Dokumentacja modułu clang LLVM: clang.llvm.org/docs/Modules.html#module-map-language
bames53
1
Och, właściwie wygląda na to, że @import sqlite3działało dla mnie, ponieważ stworzyłem dla niego własny moduł module.map i kiedy zdałem sobie sprawę, że sqlite został dołączony do systemu OS X i usunąłem moduł module.map, kompilator kontynuował używanie przestarzałego modułu.
bames53
46

Fajna odpowiedź na to pytanie znajduje się w książce Learning Cocoa with Objective-C (ISBN: 978-1-491-90139-7)

Moduły to nowy sposób włączania i łączenia plików i bibliotek z projektami. Aby zrozumieć, w jaki sposób działają moduły i jakie mają one zalety, ważne jest, aby spojrzeć wstecz na historię Objective-C i instrukcję #import Za każdym razem, gdy chcesz dołączyć plik do użytku, zazwyczaj masz jakiś kod, który wygląda następująco:

#import "someFile.h"

Lub w przypadku ram:

#import <SomeLibrary/SomeFile.h>

Ponieważ Objective-C jest nadzbiorem języka programowania C, stwierdzenie #import stanowi niewielkie udoskonalenie #includeinstrukcji C. Instrukcja #include jest bardzo prosta; kopiuje wszystko, co znajdzie w dołączonym pliku do twojego kodu podczas kompilacji. Może to czasem powodować poważne problemy. Na przykład wyobraź sobie, że masz dwa pliki nagłówkowe: SomeFileA.hi SomeFileB.h; SomeFileA.hobejmuje SomeFileB.hi SomeFileB.hobejmuje SomeFileA.h. To tworzy pętlę i może dezorientować współimpiler. Aby sobie z tym poradzić, programiści C muszą napisać zabezpieczenia przed wystąpieniem tego typu zdarzenia.

Podczas używania #importnie musisz martwić się tym problemem ani pisać osłon nagłówków, aby go uniknąć. Jednak #importnadal jest to tylko chwalebna operacja kopiowania i wklejania, powodująca wolny czas kompilacji wśród wielu innych mniejszych, ale wciąż bardzo niebezpiecznych problemów (takich jak dołączony plik przesłaniający coś, co zadeklarowałeś gdzie indziej w twoim własnym kodzie).

Moduły są próbą obejścia tego. Nie są już kopiowaniem i wklejaniem do kodu źródłowego, ale serializacją przedstawionych plików, które można zaimportować do kodu źródłowego tylko wtedy, gdy są potrzebne. Używając modułów, kod na ogół kompiluje się szybciej i jest bezpieczniejszy niż przy użyciu #include lub #import.

Wracając do poprzedniego przykładu importowania frameworka:

#import <SomeLibrary/SomeFile.h>

Aby zaimportować tę bibliotekę jako moduł, kod zostałby zmieniony na:

@import SomeLibrary;

Ma to dodatkową zaletę Xcode automatycznie łączącą strukturę SomeLibrary z projektem. Moduły pozwalają również uwzględniać tylko te elementy, których naprawdę potrzebujesz w swoim projekcie. Na przykład, jeśli chcesz użyć komponentu AwesomeObject w ramach AwesomeLibrary, zwykle musisz zaimportować wszystko, aby użyć tylko jednego elementu. Jednak za pomocą modułów możesz po prostu zaimportować określony obiekt, którego chcesz użyć:

@import AwesomeLibrary.AwesomeObject;

We wszystkich nowych projektach wykonanych w Xcode 5 moduły są domyślnie włączone. Jeśli chcesz używać modułów w starszych projektach (a naprawdę powinieneś), należy je włączyć w ustawieniach kompilacji projektu. Gdy to zrobisz, możesz używać zarówno #importi @importoświadczeń w kodzie razem bez żadnych obaw.

gbk
źródło
W moim projekcie (Xcode 6) nie ma opcji, którą po raz pierwszy uruchomiłem na Xcode 4 w celu włączenia modułów. Czy mogę jakoś dodać go ręcznie?
Awesome-o
Cel kompilacji to iOS 6, myślę, że to jest problem
Awesome-o
4

Obecnie działa tylko dla wbudowanych platform systemowych. Jeśli używasz programu #importApple, nadal importujesz UIKitstrukturę w aplikacji delegowanej, jest ona zastępowana (jeśli moduły są włączone i są rozpoznawane jako struktura systemowa), a kompilator przekształci go w import modułu, a nie import plików nagłówków . Więc pozostawienie #importbędzie tak samo jak jego konwersja do importu modułu, jeśli to możliwe

RyanTCB
źródło
2

Wygląda na to, że od XCode 7.x pojawia się wiele ostrzeżeń przy włączaniu modułu clang z CLANG_ENABLE_MODULES

Spójrz na wiele ostrzeżeń podczas budowania z Xcode 7 z bibliotekami stron trzecich

loretoparisi
źródło
Tak, ja również mam ten problem, ale ustawienie go na NIE usuwa wszystkie ostrzeżenia. Czy kiedy to zrobię, wystąpi efekt uboczny?
Satheeshwaran
1

Korzystanie z modułów ma kilka zalet. Możesz go używać tylko w ramach Apple, chyba że tworzona jest mapa modułów. @importjest nieco podobny do prekompilowanych plików nagłówkowych po dodaniu do .pchpliku, co jest sposobem na dostosowanie aplikacji do procesu kompilacji. Dodatkowo nie musisz dodawać bibliotek w stary sposób, korzystanie z nich @importjest znacznie szybsze i wydajniejsze. Jeśli nadal szukasz miłej referencji, zdecydowanie polecam przeczytanie tego artykułu .

Julian Król
źródło
0

Historia:

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

#include vs #import
.pch - Prekompilowany nagłówek

Moduł - @import

Product Name == Product Module Name 

@moduledeklaracja mówi kompilatorowi, aby załadował wstępnie skompilowany plik binarny frameworka, który skraca czas budowania . Modular Framework zawiera .modulemap[Informacje]

Jeśli funkcja modułu jest włączona w projekcie Xcode, #includea #importdyrektywy są automatycznie konwertowane na @importto, ma to wszystkie zalety

wprowadź opis zdjęcia tutaj

yoAlex5
źródło