@import vs #import - iOS 7

432

Saya bermain-main dengan beberapa fitur iOS 7 baru dan bekerja dengan beberapa Efek Gambar seperti yang dibahas dalam video WWDC "Implementing Engaging UI on iOS". Untuk menghasilkan efek blur dalam kode sumber untuk sesi, UIImagediperpanjang melalui kategori yang mengimpor UIKit seperti:

@import UIKit;

Saya pikir saya melihat sesuatu tentang ini di video sesi lain tetapi saya kesulitan menemukannya. Saya mencari informasi latar belakang kapan menggunakan ini. Bisakah itu hanya digunakan dengan kerangka kerja Apple? Apakah manfaat menggunakan arahan kompiler ini cukup sehingga saya harus kembali dan memperbarui kode lama?

jamdaddy25
sumber

Jawaban:

838

Ini fitur baru yang disebut Modul atau "impor semantik". Ada lebih banyak info di video WWDC 2013 untuk Sesi 205 dan 404 . Ini semacam implementasi yang lebih baik dari header yang sudah dikompilasi sebelumnya. Anda dapat menggunakan modul dengan salah satu kerangka kerja sistem di iOS 7 dan Mavericks. Modul adalah paket bersama dari framework yang dapat dieksekusi dan headernya dan disebut-sebut sebagai lebih aman dan lebih efisien daripada #import.

Salah satu keuntungan besar menggunakan @importadalah Anda tidak perlu menambahkan kerangka kerja di pengaturan proyek, itu dilakukan secara otomatis . Itu berarti bahwa Anda dapat melewati langkah di mana Anda mengklik tombol plus dan mencari kerangka kerja (kotak alat emas), kemudian memindahkannya ke grup "Kerangka". Ini akan menyelamatkan banyak pengembang dari pesan "kesalahan Linker" yang samar.

Anda sebenarnya tidak perlu menggunakan @importkata kunci. Jika Anda memilih untuk menggunakan modul, semua #importdan #includearahan dipetakan untuk digunakan @importsecara otomatis. Itu berarti Anda tidak perlu mengubah kode sumber Anda (atau kode sumber perpustakaan yang Anda unduh dari tempat lain). Seharusnya menggunakan modul meningkatkan kinerja build juga, terutama jika Anda belum menggunakan PCH dengan baik atau jika proyek Anda memiliki banyak file sumber kecil.

Modul sudah dibuat sebelumnya untuk sebagian besar kerangka kerja Apple (UIKit, MapKit, GameKit, dll). Anda dapat menggunakannya dengan kerangka kerja yang Anda buat sendiri: mereka dibuat secara otomatis jika Anda membuat kerangka kerja Swift di Xcode, dan Anda dapat membuat sendiri file ".modulemap" secara manual untuk perpustakaan Apple atau pihak ketiga mana pun .

Anda dapat menggunakan penyelesaian kode untuk melihat daftar kerangka kerja yang tersedia:

masukkan deskripsi gambar di sini

Modul diaktifkan secara default di proyek-proyek baru di Xcode 5 . Untuk mengaktifkannya di proyek yang lebih lama, masuk ke pengaturan membangun proyek Anda, cari "Modul" dan atur "Aktifkan Modul" ke "YA". "Kerangka Tautan" juga harus "YA":

Anda harus menggunakan Xcode 5 dan iOS 7 atau Mavericks SDK, tetapi Anda masih bisa merilis untuk OS yang lebih lama (katakanlah iOS 4.3 atau apa pun). Modul tidak mengubah cara kode Anda dibuat atau kode sumber apa pun.


Dari slide WWDC:

  • Mengimpor deskripsi semantik lengkap tentang suatu kerangka kerja
  • Tidak perlu menguraikan header
  • Cara yang lebih baik untuk mengimpor antarmuka kerangka kerja
  • Memuat representasi biner
  • Lebih fleksibel daripada tajuk yang dikompilasi
  • Kebal terhadap efek definisi makro lokal (mis. #define readonly 0x01)
  • Diaktifkan untuk proyek baru secara default

Untuk secara eksplisit menggunakan modul:

Ganti #import <Cocoa/Cocoa.h>dengan@import Cocoa;

Anda juga dapat mengimpor hanya satu tajuk dengan notasi ini:

@import iAd.ADBannerView;

Subkode melengkapi otomatis untuk Anda dalam Xcode.

raja nevan
sumber
15
@DaveDeLong & Klaas: Terima kasih! Saya harus mengakui bahwa saya tidak tahu tentang modul ketika saya pertama kali menjawab ini. Saya pergi dan menyaksikan Sesi 404 untuk mempelajarinya. Presentasi yang diberikan oleh Doug Gregor (pria LLVM) dilakukan dengan sangat baik. Ada juga pembicaraan Modul C ++ yang menjelaskan kelebihannya di sini: youtube.com/watch?v=4Xo9iH5VLQ0
raja nevan
3
@ nevan-- terima kasih atas jawabannya. Saya hanya ingin menambahkan bahwa modul saat ini belum mendukung pihak ke-3 dan kerangka kerja Anda sendiri.
jamdaddy25
Bisakah Anda menggunakan ini untuk kelas Anda sendiri?
cfischer
5
Saya pikir Anda harus dapat menambahkan kerangka kerja pihak ke-3 jika module.map yang sesuai disediakan. Dokumentasi modul dentang LLVM: clang.llvm.org/docs/Modules.html#module-map-language
bames53
1
Oh, sebenarnya sepertinya @import sqlite3berhasil bagi saya karena saya telah membuat module.map saya sendiri dan ketika saya menyadari sqlite dimasukkan dalam OS X dan menghapus module.map saya, kompiler terus menggunakan modul basi.
bames53
46

Jawaban yang bagus dapat Anda temukan dalam buku Learning Cocoa with Objective-C (ISBN: 978-1-491-90139-7)

Modul adalah cara baru untuk memasukkan dan menautkan file dan perpustakaan ke proyek Anda. Untuk memahami bagaimana modul bekerja dan manfaat apa yang mereka miliki, penting untuk melihat kembali sejarah Objective-C dan pernyataan #import Setiap kali Anda ingin menyertakan file untuk digunakan, Anda biasanya akan memiliki beberapa kode yang terlihat seperti ini:

#import "someFile.h"

Atau dalam hal kerangka kerja:

#import <SomeLibrary/SomeFile.h>

Karena Objective-C adalah superset dari bahasa pemrograman C, pernyataan #import adalah perbaikan kecil pada #includepernyataan C. Pernyataan #include sangat sederhana; itu menyalin semua yang ditemukan dalam file yang disertakan ke dalam kode Anda selama kompilasi. Ini kadang-kadang dapat menyebabkan masalah yang signifikan. Misalnya, bayangkan Anda memiliki dua file header: SomeFileA.hdan SomeFileB.h; SomeFileA.htermasuk SomeFileB.h, dan SomeFileB.htermasuk SomeFileA.h. Ini menciptakan loop, dan dapat membingungkan coimpiler. Untuk mengatasi hal ini, programmer C harus menulis penjaga terhadap jenis peristiwa ini agar tidak terjadi.

Saat menggunakan #import, Anda tidak perlu khawatir tentang masalah ini atau menulis pelindung kepala untuk menghindarinya. Namun, #importmasih merupakan tindakan salin dan tempel yang dimuliakan, menyebabkan waktu kompilasi yang lambat di antara sejumlah masalah lain yang lebih kecil namun masih sangat berbahaya (seperti file yang disertakan menimpa sesuatu yang telah Anda nyatakan di tempat lain dalam kode Anda sendiri.)

Modul adalah upaya untuk mengatasi ini. Mereka bukan lagi copy-paste ke kode sumber, tetapi representasi serial dari file yang disertakan yang dapat diimpor ke kode sumber Anda hanya kapan dan di mana mereka dibutuhkan. Dengan menggunakan modul, kode umumnya akan dikompilasi lebih cepat, dan lebih aman daripada menggunakan #include atau #import.

Kembali ke contoh mengimpor kerangka kerja sebelumnya:

#import <SomeLibrary/SomeFile.h>

Untuk mengimpor perpustakaan ini sebagai modul, kode akan diubah menjadi:

@import SomeLibrary;

Ini memiliki bonus tambahan Xcode yang menghubungkan kerangka SomeLibrary ke proyek secara otomatis. Modul juga memungkinkan Anda untuk hanya memasukkan komponen yang benar-benar Anda butuhkan ke dalam proyek Anda. Misalnya, jika Anda ingin menggunakan komponen AwesomeObject dalam kerangka AwesomeLibrary, biasanya Anda harus mengimpor semuanya hanya untuk menggunakan bagian yang satu. Namun, menggunakan modul, Anda bisa mengimpor objek tertentu yang ingin Anda gunakan:

@import AwesomeLibrary.AwesomeObject;

Untuk semua proyek baru yang dibuat dalam Xcode 5, modul diaktifkan secara default. Jika Anda ingin menggunakan modul dalam proyek yang lebih lama (dan Anda benar-benar harus) mereka harus diaktifkan di pengaturan pembangunan proyek. Setelah Anda melakukannya, Anda dapat menggunakan keduanya #importdan @importpernyataan dalam kode Anda bersama-sama tanpa masalah.

gbk
sumber
Tidak ada opsi dalam proyek saya (Xcode 6) yang pertama kali saya mulai di Xcode 4 untuk mengaktifkan modul. Bisakah saya menambahkannya secara manual?
Hebat-o
Membangun target adalah iOS 6, saya pikir ini masalahnya
Keren-o
4

Saat ini hanya berfungsi untuk kerangka kerja sistem bawaan. Jika Anda menggunakan #importseperti apel, masih mengimpor UIKitkerangka kerja dalam delegasi aplikasi, kerangka itu diganti (jika modul aktif dan dikenali sebagai kerangka kerja sistem) dan kompiler akan memetakannya kembali menjadi modul impor dan bukan impor file header. . Jadi meninggalkannya #importakan sama dengan yang dikonversi ke modul impor jika memungkinkan pula

RyanTCB
sumber
2

Tampaknya sejak XCode 7.xa banyak peringatan keluar ketika mengaktifkan modul dentang dengan CLANG_ENABLE_MODULES

Lihatlah Banyak peringatan saat membangun dengan Xcode 7 dengan perpustakaan pihak ke-3

loretoparisi
sumber
Ya saya juga memiliki masalah ini, tetapi mengaturnya untuk TIDAK menghapus semua peringatan. Apakah akan ada efek samping ketika saya melakukan ini ??
Satheeshwaran
1

Ada beberapa manfaat menggunakan modul. Anda dapat menggunakannya hanya dengan kerangka kerja Apple kecuali modul peta dibuat. @importsedikit mirip dengan file header pra-kompilasi ketika ditambahkan ke .pchfile yang merupakan cara untuk menyempurnakan aplikasi proses kompilasi. Selain itu Anda tidak perlu menambahkan perpustakaan dengan cara lama, menggunakan @importsebenarnya jauh lebih cepat dan efisien. Jika Anda masih mencari referensi yang bagus, saya akan sangat menyarankan Anda membaca artikel ini .

Julian Król
sumber
0

Sejarah:

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

#include vs #import
.pch - Header terkompilasi

Modul - @import

Product Name == Product Module Name 

@moduledeklarasi mengatakan kepada compiler untuk memuat binary framework yang dikompilasi yang mengurangi waktu pembangunan . Kerangka Modular berisi .modulemap[Tentang]

Jika fitur modul diaktifkan di proyek Xcode #includedan #importarahan secara otomatis dikonversi ke @importyang membawa semua keuntungan

masukkan deskripsi gambar di sini

yoAlex5
sumber