web-dev-qa-db-ja.com

@import vs #import - iOS 7

私は、iOS 7の新機能のいくつかを試していて、WWDCビデオ「iOSでEngaging UIを実装する」で説明されているImage Effectsのいくつかを使って作業しています。セッションのソースコード内でぼかし効果を生成するために、UIImageは次のようにUIKitをインポートするカテゴリによって拡張されました。

@import UIKit;

私はこれについて別のセッションビデオで何かを見たと思いますが、それを見つけるのに問題があります。いつこれを使用するかについての背景情報を探しています。 Appleのフレームワークでしか使えませんか?このコンパイラ指令を使用する利点は、元のコードに戻って更新するのに十分なものですか?

417
jamdaddy25

これは、Modulesまたは「セマンティックインポート」と呼ばれる新しい機能です。 WWDC 201 セッションのビデオ 205 および 404 に詳細があります。これは、プリコンパイル済みヘッダーのより良い実装の一種です。 iOS 7およびMavericksのシステムフレームワークのいずれかでモジュールを使用できます。モジュールは、フレームワーク実行可能ファイルとヘッダーのパッケージであり、 #importより安全で効率的です。

@importを使用する大きな利点の1つは、プロジェクト設定にフレームワークを追加する必要がなく、自動的に行われることです。つまり、プラスボタンをクリックしてフレームワーク(ゴールデンツールボックス)を検索するステップをスキップし、それを「Frameworks」グループに移動できます。多くの開発者を不可解な「リンカーエラー」メッセージから救います。

実際に@importキーワードを使用する必要はありません。モジュールの使用を選択した場合、すべての#importおよび#includeディレクティブは、@importを自動的に使用するようにマップされます。つまり、ソースコード(または他の場所からダウンロードしたライブラリのソースコード)を変更する必要はありません。おそらくモジュールを使用すると、特にPCHを適切に使用していない場合やプロジェクトに多数の小さなソースファイルがある場合に、ビルドのパフォーマンスも向上します。

モジュールは、ほとんどのAppleフレームワーク(UIKit、MapKit、GameKitなど)用に事前に構築されています。自分で作成したフレームワークでそれらを使用できます。XcodeでSwiftフレームワークを作成すると自動的に作成され、 any Appleまたはサードパーティライブラリ

コード補完を使用して、利用可能なフレームワークのリストを表示できます。

enter image description here

モジュールは、Xcode 5の新しいプロジェクトでデフォルトで有効になっています。古いプロジェクトでそれらを有効にするには、プロジェクトのビルド設定に移動して、「モジュール」を検索し、「モジュールを有効にする」を「はい」に設定します。 「Link Frameworks」も「YES」にする必要があります。

Xcode 5とiOS 7またはMavericks SDKを使用する必要がありますが、古いOS(iOS 4.3など)向けにリリースすることはできます。 モジュールは、コードのビルド方法やソースコードを変更しません。


WWDCスライドから:

  • フレームワークの完全なセマンティック記述をインポートします
  • ヘッダーを解析する必要はありません
  • フレームワークのインターフェースをインポートするより良い方法
  • バイナリ表現をロードします
  • プリコンパイル済みヘッダーよりも柔軟
  • ローカルマクロ定義の影響を受けません(例:#define readonly 0x01
  • デフォルトで新しいプロジェクトに対して有効化

モジュールを明示的に使用するには:

#import <Cocoa/Cocoa.h>@import Cocoa;に置き換えます

この表記法でヘッダーを1つだけインポートすることもできます。

@import iAd.ADBannerView;

Xcodeのサブモジュールは自動補完されます。

830
nevan king

「Objective-Cでココアを学ぶ」(ISBN:978-1-491-90139-7)という本で見つけることができる素敵な答え

モジュールは、ファイルやライブラリをプロジェクトに含めたりリンクしたりするための新しい手段です。モジュールの動作とその利点を理解するためには、Objective-Cと#importステートメントの歴史を振り返ることが重要です。使用するファイルをインクルードしたい場合は、通常、次のようなコードがあります。

#import "someFile.h"

あるいはフレームワークの場合:

#import <SomeLibrary/SomeFile.h>

Objective-CはCプログラミング言語のスーパーセットであるため、#importステートメントはCの#includeステートメントを少し改良したものです。 #includeステートメントはとても単純です。コンパイル中に、インクルードファイルで見つかったものすべてをコードにコピーします。これは時々重大な問題を引き起こす可能性があります。たとえば、SomeFileA.hSomeFileB.hの2つのヘッダーファイルがあるとします。 SomeFileA.hSomeFileB.hを含み、SomeFileB.hSomeFileA.hを含みます。これはループを作り、そしてcoimpilerを混乱させる可能性があります。これに対処するために、Cプログラマーはこの種のイベントが発生するのを防ぐためにガードを書く必要があります。

#importを使用するときは、この問題を心配したり、それを回避するためにヘッダーガードを作成したりする必要はありません。しかし、#importはまだ単なる賛美されたコピーアンドペーストアクションであり、他の小さいながらも非常に危険な問題のホスト間でコンパイル時間が遅くなります(インクルードファイルが自分のコードの別の場所で宣言したものを上書きするなど)。

モジュールはこれを回避するための試みです。それらはもはやソースコードへのコピーアンドペーストではなく、含まれるファイルのシリアル化された表現であり、必要なときと場所でのみソースコードにインポートすることができます。モジュールを使うことで、コードは一般的に速くコンパイルされ、#includeや#importを使うより安全です。

フレームワークをインポートする前の例に戻ります。

#import <SomeLibrary/SomeFile.h>

このライブラリをモジュールとしてインポートするには、コードを次のように変更します。

@import SomeLibrary;

これはSomeLibraryフレームワークを自動的にプロジェクトにリンクするXcodeの追加ボーナスを持っています。モジュールを使用すると、本当に必要なコンポーネントだけをプロジェクトに含めることもできます。たとえば、AwesomeLibraryフレームワークのAwesomeObjectコンポーネントを使用する場合は、通常、1つのピースを使用するためだけにすべてをインポートする必要があります。ただし、モジュールを使用すると、使用したい特定のオブジェクトをインポートすることができます。

@import AwesomeLibrary.AwesomeObject;

Xcode 5で作成されたすべての新しいプロジェクトでは、モジュールはデフォルトで有効になっています。古いプロジェクトでモジュールを使用したい場合(そして本当にそうするべきです)、それらはプロジェクトのビルド設定で有効にされなければなりません。それができれば、#import@importの両方のステートメントを心配することなく一緒に使うことができます。

44
gbk

現時点では組み込みのシステムフレームワークに対してのみ機能します。あなたがAppleのように#importを使っている場合でも、アプリデリゲートでUIKitフレームワークをインポートします(モジュールがオンになっていてシステムフレームワークとして認識されている場合)。とにかくファイル。それで、#importを残すことは、とにかく可能であればそれがモジュールインポートに変換されるのとちょうど同じでしょう

3
RyanTCB

Xcode 7.x以降、CLANG_ENABLE_MODULESを使ってclangモジュールを有効にすると多くの警告が出てくるようです

Xcode 7とサードパーティ製ライブラリを併用してビルドする際の多くの警告 - を見てください

2
loretoparisi

Amodule[構造] は、プリプロセッサテキストインクルードメカニズムをClangがセマンティックインポートと呼ぶものに置き換えることにより、システムフレームワークおよびライブラリを操作するためのより良い方法を提供します。モジュールをインポートするには、@importまたは#includeプリプロセッサディレクティブの代わりに#import宣言を使用します

コンパイラーは、モジュールのインポート@importを検出すると、スタンドアロンのprecompiledバージョンのバイナリーをロードします。また、モジュールへのリンクを自動的に処理するため、Xcodeでフレームワークを手動で追加する必要がなくなります。モジュールは一度だけコンパイルされるため、prefix.pchにフレームワークヘッダーを含める利点はなくなりました。その結果、プリコンパイルプレフィックスヘッダービルド設定はXcodeでデフォルトでNOになりました。

@importは、次の問題を解決します。

  • フレームワークの完全なセマンティック記述をインポートします
  • ヘッダーを解析する必要はありません
  • バイナリ表現をロードします
  • プリコンパイル済みヘッダーよりも柔軟
  • .pchファイルを維持する必要はありません

#importおよび#includeディレクティブは、舞台裏で自動的に@importに変換されるため、作業なしでモジュールの利点を得ることができます。

独自のframeworkを構築すると、Xcodeはumbrella headerを含むモジュールマップを生成します[約]

Objective-Cを使用して独自のlibraryを構築する場合、独自のモジュールマップを作成する必要があります(。modulemap)およびその内容が最新であることを確認してください。 [ライブラリを作成する][セットアップモジュールマップ][カスタムモジュールマップ]

#mport VS #include

続きを読む herehere

1
yoAlex5

モジュールを使用する利点はいくつかあります。モジュールマップが作成されていない限り、あなたはそれをAppleのフレームワークでのみ使うことができます。 @importは、.pchファイルに追加されたときにヘッダーファイルをプリコンパイルするのと少し似ています。これは、コンパイルプロセスを調整する方法です。さらに、古い方法でライブラリを追加する必要はありません。実際には@importを使用する方がはるかに速く効率的です。それでもいい参照を探しているなら、 この記事 を読むことを強くお勧めします。

1
Julian Król