@import vs #import - iOS 7

432

Я играю с некоторыми новыми функциями iOS 7 и работаю с некоторыми графическими эффектами, которые обсуждались в видео WWDC «Внедрение привлекательного пользовательского интерфейса на iOS». Для создания эффекта размытия в исходном коде сеанса UIImageбыла расширена категория, которая импортирует UIKit следующим образом:

@import UIKit;

Я думаю, что видел что-то об этом в другом видео сеанса, но у меня проблемы с поиском. Я ищу любую справочную информацию о том, когда использовать это. Может ли он использоваться только с фреймворками Apple? Достаточно ли преимуществ использования этой директивы компилятора, чтобы я мог вернуться и обновить старый код?

jamdaddy25
источник
stackoverflow.com/questions/29701647/…
Удай Сраван К

Ответы:

838

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

Одним из больших преимуществ использования @importявляется то, что вам не нужно добавлять каркас в настройках проекта, это делается автоматически . Это означает, что вы можете пропустить шаг, на котором вы нажимаете кнопку «плюс» и ищите фреймворк (золотой набор инструментов), а затем перемещаете его в группу «Фреймворки». Это спасет многих разработчиков от загадочных сообщений об ошибках компоновщика.

Вам на самом деле не нужно использовать @importключевое слово. Если вы решите использовать модули, все #importи #includeдирективы будут сопоставлены для использования @importавтоматически. Это означает, что вам не нужно менять исходный код (или исходный код библиотек, которые вы загружаете из других источников). Предположительно, использование модулей также повышает производительность сборки, особенно если вы плохо используете PCH или если в вашем проекте много небольших исходных файлов.

Модули предварительно созданы для большинства платформ 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
Неван Кинг,
3
@ Неван-- спасибо за ответ. Я просто хотел добавить, что модули пока не поддерживают сторонние и ваши собственные фреймворки.
jamdaddy25
Вы можете использовать это для своих собственных классов?
cfischer
5
Я думаю, что вы должны иметь возможность @import сторонних фреймворков, если предоставляется соответствующий module.map. Документация к модулю LLVM clang: clang.llvm.org/docs/Modules.html#module-map-language
bames53
1
О, на самом деле это выглядит как @import sqlite3работало для меня, потому что я создал для него свой собственный module.map, и когда я понял, что sqlite был включен в OS X и удалил мой module.map, компилятор продолжил использовать устаревший модуль.
bames53
46

Хороший ответ вы можете найти в книге «Изучение какао с Objective-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. Это создает цикл и может запутать coimpiler. Чтобы справиться с этим, программисты на Си должны написать защиту от такого типа событий.

При использовании #importвам не нужно беспокоиться об этой проблеме или писать защиту заголовков, чтобы избежать ее. Тем не менее, #importэто всего лишь прославленное действие копирования и вставки, вызывающее медленное время компиляции среди множества других небольших, но все же очень опасных проблем (таких как включенный файл, переопределяющий то, что вы объявили в другом месте своего собственного кода).

Модули - это попытка обойти это. Они больше не являются копией и вставкой в ​​исходный код, а представляют собой сериализованное представление включенных файлов, которые могут быть импортированы в ваш исходный код только тогда и там, где они необходимы. При использовании модулей код обычно компилируется быстрее и безопаснее, чем с использованием #include или #import.

Возвращаясь к предыдущему примеру импорта фреймворка:

#import <SomeLibrary/SomeFile.h>

Чтобы импортировать эту библиотеку как модуль, код будет изменен на:

@import SomeLibrary;

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

@import AwesomeLibrary.AwesomeObject;

Для всех новых проектов, сделанных в Xcode 5, модули включены по умолчанию. Если вы хотите использовать модули в старых проектах (и вам это действительно нужно), их нужно будет включить в настройках сборки проекта. Как только вы это сделаете, вы можете без проблем использовать оба оператора #importи @importоператоры в своем коде.

GBK
источник
В моем проекте (Xcode 6) нет опции, которую я впервые запустил в Xcode 4 для включения модулей. Можно ли как-нибудь добавить это вручную?
Великолепно,
Цель сборки - iOS 6, я думаю, что это проблема
Awesome-o
4

В настоящее время он работает только для встроенных системных платформ. Если вы используете #importкак apple, по-прежнему импортируете UIKitфреймворк в делегат приложения, он заменяется (если модули включены и распознаются как системный фреймворк), и компилятор переназначит его для импорта модуля, а не для импорта файлов заголовка в любом случае. , Таким образом, оставление #importобъекта будет таким же, как и его преобразование в модуль импорта, где это возможно.

RyanTCB
источник
2

Похоже, что с XCode 7.x появляется много предупреждений при включении модуля clang с CLANG_ENABLE_MODULES

Посмотрите много предупреждений при сборке с Xcode 7 с сторонними библиотеками

loretoparisi
источник
Да, у меня тоже есть эта проблема, но установка на НЕТ удаляет все предупреждения. Будет ли побочный эффект, когда я сделаю это?
Satheeshwaran
1

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

Джулиан Крол
источник
0

История:

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

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

Модуль - @import

Product Name == Product Module Name 

@moduleОбъявление говорит компилятору загружать предварительно скомпилированный двоичный файл фреймворка, который сокращает время сборки . Модульная структура содержит .modulemap[О]

Если в проекте Xcode включена функция модуля #includeи #importдирективы автоматически конвертируются, @importэто дает все преимущества

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

yoAlex5
источник