@import vs #import - iOS 7


432

Я граю з деякими новими функціями iOS 7 і працюю з деякими ефектами зображення, як обговорювалося у відео WWDC "Реалізація залученого інтерфейсу на iOS". Для створення ефекту розмиття у вихідному коді сеансу UIImageбуло розширено через категорію, яка імпортує UIKit так:

@import UIKit;

Я думаю, що я щось про це побачив у іншому відео сеансу, але у мене виникають проблеми з його пошуком. Я шукаю довідкову інформацію про те, коли це використовувати. Чи можна його використовувати лише в рамках Apple? Чи достатньо переваг використання цієї директиви компілятора, щоб я міг повернутися та оновити старий код?


Відповіді:


838

Це нова функція під назвою Модулі або "семантичний імпорт". Більше інформації міститься у відеозаписах WWDC 2013 для сесій 205 та 404 . Це наче краще втілення попередньо складених заголовків. Ви можете використовувати модулі з будь-якою із системних рамок у iOS 7 та Mavericks. Модулі - це упаковка разом із виконуваною рамкою та її заголовками, і вони рекламуються як більш безпечні та ефективніші, ніж #import.

Однією з великих переваг використання @importє те, що вам не потрібно додавати рамки в налаштування проекту, це робиться автоматично . Це означає, що ви можете пропустити крок, на якому натискаєте кнопку плюс, і шукати рамку (золоту панель інструментів), а потім переміщувати її до групи «Рамки». Це врятує багатьох розробників від криптичних повідомлень про помилку "Linker".

Насправді не потрібно використовувати @importключове слово. Якщо ви ввімкнули використання модулів, всі #importта #includeдирективи відображаються @importавтоматично для використання . Це означає, що вам не потрібно змінювати свій вихідний код (або вихідний код бібліотек, які ви завантажуєте з іншого місця). Нібито використання модулів також покращує продуктивність збірки, особливо якщо ви не використовуєте ПКР або якщо у вашому проекті є багато невеликих вихідних файлів.

Модулі попередньо побудовані для більшості фреймворків Apple (UIKit, MapKit, GameKit тощо). Ви можете використовувати їх із створеними вами рамками: вони створюються автоматично, якщо ви створюєте рамку Swift в Xcode, і ви можете вручну створити файл ".modulemap" самостійно для будь-якої бібліотеки Apple чи сторонніх бібліотек .

Ви можете скористатися доповненням коду, щоб переглянути список доступних фреймів:

введіть тут опис зображення

Модулі увімкнено за замовчуванням у нових проектах у Xcode 5 . Щоб увімкнути їх у старішому проекті, увійдіть у налаштування збирання проекту, знайдіть "Модулі" та встановіть для "Увімкнути модулі" значення "ТАК". "Рамки посилань" також повинні бути "ТАК":

Ви повинні використовувати Xcode 5 та iOS 7 або Mavericks SDK, але ви все ще можете випускати для старих ОС (скажімо, iOS 4.3 або будь-яку іншу). Модулі не змінюють спосіб побудови вашого коду чи будь-якого вихідного коду.


З слайдів WWDC:

  • Імпортує повний семантичний опис фрейму
  • Не потрібно розбирати заголовки
  • Кращий спосіб імпортувати інтерфейс рамки
  • Завантажує двійкове представлення
  • Більш гнучкі, ніж попередньо складені заголовки
  • Захисний від впливу локальних макроозначень (наприклад #define readonly 0x01)
  • Увімкнено для нових проектів за замовчуванням

Щоб явно використовувати модулі:

Замініть #import <Cocoa/Cocoa.h>на@import Cocoa;

Ви також можете імпортувати лише один заголовок із цим позначенням:

@import iAd.ADBannerView;

Підмодулі для вас автоматично заповнюються в Xcode.


15
@DaveDeLong & Klaas: Дякую! Я повинен визнати, що я нічого не знав про модулі, коли вперше відповів на це. Я пішов і дивився сесію 404, щоб дізнатися це. Презентація, яку дав Даг Грегор (хлопець LLVM), була дійсно добре виконана. Тут також розмовляють модулі C ++, де пояснюються переваги тут: youtube.com/watch?v=4Xo9iH5VLQ0
nevan king

3
@ nevan-- дякую за відповідь. Я просто хотів додати, що модулі наразі ще не підтримують сторонні та ваші власні рамки.
jamdaddy25

Чи можете ви використовувати це для власних занять?
cfischer

5
Я думаю, ви повинні мати можливість @import сторонніх фреймворків, якщо надається відповідна module.map. Документація по модулю LLVM: clang.llvm.org/docs/Modules.html#module-map-language
bames53

1
О, насправді це схоже @import sqlite3на мене працювало, тому що я створив власну module.map для цього, і коли я зрозумів, що sqlite був включений в OS X і видалив мій module.map, компілятор продовжував використовувати застарілий модуль.
bames53

46

Гарну відповідь ви можете знайти в книзі «Навчання какао з ціллю-C» (ISBN: 978-1-491-90139-7)

Модулі - це новий засіб включення та з'єднання файлів і бібліотек у ваші проекти. Щоб зрозуміти, як працюють модулі та які переваги вони мають, важливо зазирнути назад в історію Objective-C та оператор #import Кожен раз, коли ви хочете включити файл для використання, як правило, ви маєте такий код, який виглядає приблизно так:

#import "someFile.h"

Або у випадку з рамками:

#import <SomeLibrary/SomeFile.h>

Оскільки Objective-C є набором мови програмування C, #import #includeзаява є незначним уточненням заяви C. Заява #include дуже проста; він копіює все, що знаходиться у включеному файлі, у ваш код під час компіляції. Іноді це може спричинити значні проблеми. Наприклад, уявіть, що у вас є два файли заголовка: SomeFileA.hі SomeFileB.h; SomeFileA.hвключає SomeFileB.hі SomeFileB.hвключає SomeFileA.h. Це створює цикл і може переплутати коімпілер. Щоб вирішити це, програмістам C доводиться писати запобіжники проти подібних подій.

Під час використання #importвам не потрібно хвилюватися з приводу цієї проблеми або писати заголовки заголовків, щоб уникнути цього. Однак #importце все-таки лише прославлена ​​дія копіювання та вставки, що спричиняє повільний час компіляції серед безлічі інших менших, але все ще дуже небезпечних проблем (наприклад, включений файл, що перекриває щось, про що ви заявили десь у власному коді.)

Модулі - це спроба обійти це. Вони більше не є копіюванням та вставкою у вихідний код, а серійним поданням включених файлів, які можна імпортувати у ваш вихідний код лише тоді, коли та де вони потрібні. Використовуючи модулі, код, як правило, компілюється швидше і є безпечнішим, ніж використання #include або #import.

Повернення до попереднього прикладу імпорту рамки:

#import <SomeLibrary/SomeFile.h>

Щоб імпортувати цю бібліотеку як модуль, код буде змінено на:

@import SomeLibrary;

Це має додатковий бонус Xcode, який автоматично пов'язує рамки SomeLibrary в проект. Модулі також дозволяють включати в проект лише ті компоненти, які вам справді потрібні. Наприклад, якщо ви хочете використовувати компонент AwesomeObject в рамках AwesomeLibrary, зазвичай вам доведеться імпортувати все лише для використання одного елемента. Однак, використовуючи модулі, ви можете просто імпортувати конкретний об'єкт, який ви хочете використовувати:

@import AwesomeLibrary.AwesomeObject;

Для всіх нових проектів, зроблених у Xcode 5, модулі включені за замовчуванням. Якщо ви хочете використовувати модулі в старих проектах (і вам справді слід), їх потрібно буде включити в налаштуваннях проекту. Після цього ви можете без перешкод використовувати разом #importі @importвиписки у своєму коді.


У моєму проекті (Xcode 6) немає жодного варіанту, який я вперше запустив у Xcode 4 для включення модулів. Чи можу я додати його вручну якось?
Awesome-o

Ціль збирання iOS 6, я думаю, що це проблема
Awesome-o

4

Наразі він працює лише для вбудованих системних рамок. Якщо ви використовуєте, #importяк Apple, все-таки імпортують UIKitфреймворк у делегат програми, його замінюють (якщо модулі ввімкнено і його визнано системною рамкою), і компілятор перезавантажить його як імпорт модуля, а не імпорт файлів заголовка . Тож залишення #importволі буде таким самим, як його перетворене на імпорт модуля, де це можливо в будь-якому випадку


2

Здається, що з XCode 7.xa виходить багато попереджень при включенні модуля clang з CLANG_ENABLE_MODULES

Погляньте на безліч попереджень під час створення Xcode 7 з сторонніми бібліотеками


Так, у мене теж є ця проблема, але встановлення значення "НІ" видаляє всі попередження. Чи буде побічний ефект, коли я це роблю ??
Satheeshwaran

1

Є кілька переваг використання модулів. Ви можете використовувати його лише в рамках Apple, якщо карта модуля не створена. @importтрохи схожий на попередню компіляцію файлів заголовків, коли вони додаються до .pchфайлу, що є способом налаштування програми компіляції. Крім того, вам не доведеться додавати бібліотеки по-старому, використовуючи @importнабагато швидше та ефективніше. Якщо ви все ще шукаєте приємну довідку, я дуже рекомендую вам прочитати цю статтю .


0

Історія:

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

#include vs
#import .pch - попередньо складений заголовок

Модуль - @import

Product Name == Product Module Name 

@moduleДекларація каже компілятору завантажити попередньо складений бінарний фреймворк, який зменшує час побудови . Модульна рамка містить .modulemap[About]

Якщо функція модуля увімкнена в проекті Xcode, #includeа #importдирективи автоматично перетворюються на це, @importщо приносить усі переваги

введіть тут опис зображення

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.