@import vs #import - iOS 7


432

ฉันกำลังเล่นกับฟีเจอร์ใหม่ของ iOS 7 และทำงานกับเอฟเฟกต์ภาพบางส่วนตามที่กล่าวไว้ในวิดีโอ WWDC "Implementing Engaging UI บน iOS" สำหรับการสร้างเอฟเฟกต์เบลอภายในซอร์สโค้ดสำหรับเซสชันนั้นUIImageได้ขยายผ่านหมวดหมู่ที่นำเข้า UIKit ดังนี้:

@import UIKit;

ฉันคิดว่าฉันเห็นบางสิ่งเกี่ยวกับสิ่งนี้ในวิดีโอเซสชั่นอื่น แต่ฉันมีปัญหาในการค้นหา ฉันกำลังมองหาข้อมูลพื้นหลังใด ๆ เมื่อใช้นี้ สามารถใช้กับกรอบงานของ Apple ได้เท่านั้นหรือไม่ ประโยชน์ของการใช้คำสั่งคอมไพเลอร์นี้เพียงพอที่ฉันควรกลับไปและอัปเดตรหัสเก่าหรือไม่


คำตอบ:


838

มันเป็นคุณสมบัติใหม่ที่เรียกว่าModulesหรือ "semantic import" มีข้อมูลเพิ่มเติมอยู่ในWWDC 2013วิดีโอสำหรับเซสชัน205และ404 มันเป็นการใช้งานที่ดีขึ้นของส่วนหัวที่รวบรวมไว้ล่วงหน้า คุณสามารถใช้โมดูลกับกรอบระบบใด ๆ ใน iOS 7 และ Mavericks #importโมดูลจะมีการบรรจุภัณฑ์กันปฏิบัติการกรอบและมันของส่วนหัวและได้รับการขนานนามว่าเป็นที่ปลอดภัยและมีประสิทธิภาพมากกว่า

หนึ่งในข้อได้เปรียบใหญ่ของการใช้@importคือการที่คุณไม่จำเป็นต้องเพิ่มกรอบในการตั้งค่าโครงการก็ทำได้โดยอัตโนมัติ ซึ่งหมายความว่าคุณสามารถข้ามขั้นตอนที่คุณคลิกปุ่มบวกและค้นหากรอบงาน (กล่องเครื่องมือสีทอง) จากนั้นย้ายไปยังกลุ่ม "กรอบงาน" มันจะบันทึกนักพัฒนาจำนวนมากจากข้อความ "Linker error" ที่เป็นความลับ

คุณไม่จำเป็นต้องใช้@importคำหลักจริงๆ หากคุณเลือกใช้โมดูลทั้งหมด#importและ#includeคำสั่งจะถูกแมปเพื่อใช้งาน@importโดยอัตโนมัติ ซึ่งหมายความว่าคุณไม่จำเป็นต้องเปลี่ยนซอร์สโค้ดของคุณ (หรือซอร์สโค้ดของไลบรารีที่คุณดาวน์โหลดจากที่อื่น) การใช้โมดูลควรปรับปรุงประสิทธิภาพการสร้างเช่นกันโดยเฉพาะอย่างยิ่งถ้าคุณไม่ได้ใช้ PCH อย่างดีหรือโครงการของคุณมีไฟล์ต้นฉบับขนาดเล็กจำนวนมาก

โมดูลถูกสร้างไว้ล่วงหน้าสำหรับเฟรมเวิร์กส่วนใหญ่ของ Apple (UIKit, MapKit, GameKit ฯลฯ ) คุณสามารถใช้พวกเขาด้วยกรอบคุณสร้างขึ้นเองที่พวกเขาจะถูกสร้างขึ้นโดยอัตโนมัติหากคุณสร้างกรอบสวิฟท์ใน Xcode และคุณสามารถสร้าง ".modulemap" แฟ้มตัวเองสำหรับแอปเปิ้ลหรือบุคคลที่ 3 ห้องสมุด

คุณสามารถใช้การเติมโค้ดเพื่อดูรายการเฟรมเวิร์กที่มีอยู่:

ป้อนคำอธิบายรูปภาพที่นี่

โมดูลจะเปิดใช้งานโดยเริ่มต้นในโครงการใหม่ใน Xcode 5 หากต้องการเปิดใช้งานในโครงการรุ่นเก่าให้ไปที่การตั้งค่าการสร้างโครงการค้นหา "โมดูล" และตั้งค่า "เปิดใช้งานโมดูล" เป็น "YES" "Link Frameworks" ควรเป็น "YES" ด้วย:

คุณต้องใช้ Xcode 5 และ iOS 7 หรือ Mavericks SDK แต่คุณยังสามารถปล่อยสำหรับระบบปฏิบัติการรุ่นเก่า (เช่น iOS 4.3 หรืออะไรก็ตาม) โมดูลจะไม่เปลี่ยนแปลงวิธีการสร้างรหัสของคุณหรือซอร์สโค้ดใด ๆ


จากสไลด์ WWDC:

  • นำเข้าคำอธิบายความหมายสมบูรณ์ของกรอบงาน
  • ไม่จำเป็นต้องแยกวิเคราะห์ส่วนหัว
  • วิธีที่ดีกว่าในการนำเข้าส่วนต่อประสานของกรอบงาน
  • โหลดการแทนค่าฐานสอง
  • มีความยืดหยุ่นมากกว่าส่วนหัวที่คอมไพล์แล้ว
  • ภูมิคุ้มกันผลกระทบของคำจำกัดความแมโครท้องถิ่น (เช่น#define readonly 0x01)
  • เปิดใช้งานสำหรับโครงการใหม่ตามค่าเริ่มต้น

ในการใช้โมดูลอย่างชัดเจน:

แทนที่#import <Cocoa/Cocoa.h>ด้วย@import Cocoa;

นอกจากนี้คุณยังสามารถนำเข้าเพียงหนึ่งส่วนหัวด้วยสัญลักษณ์นี้

@import iAd.ADBannerView;

submodules การเติมข้อความอัตโนมัติให้คุณใน Xcode


15
@DaveDeLong & Klaas: ขอบคุณ! ฉันต้องยอมรับว่าฉันไม่รู้อะไรเกี่ยวกับโมดูลเมื่อฉันตอบคำถามนี้เป็นครั้งแรก ฉันไปดูเซสชัน 404 เพื่อเรียนรู้ งานนำเสนอที่ Doug Gregor (คน LLVM) นั้นทำได้ดีมาก นอกจากนี้ยังมีโมดูล C ++ ที่อธิบายถึงข้อดีที่นี่: youtube.com/watch?v=4Xo9iH5VLQ0
nevan king

3
@ nevan-- ขอบคุณสำหรับคำตอบ ฉันแค่อยากจะเพิ่มโมดูลที่ยังไม่สนับสนุนบุคคลที่สามและกรอบงานของคุณเอง
jamdaddy25

คุณสามารถใช้สิ่งนี้สำหรับชั้นเรียนของคุณเองได้หรือไม่?
cfischer

5
ฉันคิดว่าคุณควรจะสามารถ @import framework อื่น ๆ หากมี 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สิ่งนี้สร้างลูปและสามารถสร้างความสับสน เพื่อจัดการกับสิ่งนี้โปรแกรมเมอร์ C ต้องเขียน guards กับเหตุการณ์ประเภทนี้ไม่ให้เกิดขึ้น

เมื่อใช้#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 สำหรับการเปิดใช้งานโมดูล ฉันจะเพิ่มมันด้วยตัวเองได้ไหม?
เลิศ

Build เป้าหมายคือ iOS 6 ฉันคิดว่านี่เป็นปัญหา
Awesome-o

4

ขณะนี้มันใช้งานได้เฉพาะกับเฟรมเวิร์กระบบที่มีอยู่แล้ว หากคุณใช้#importเช่น apple ยังคงนำเข้า UIKitเฟรมเวิร์กในแอพผู้รับมอบสิทธิ์มันจะถูกแทนที่ (หากโมดูลเปิดอยู่และได้รับการยอมรับว่าเป็นเฟรมเวิร์กระบบ) และคอมไพเลอร์จะทำการแมปใหม่ให้เป็นการนำเข้าโมดูล . ดังนั้นการปล่อย#importจะเหมือนกับแปลงเป็นการนำเข้าโมดูลที่เป็นไปได้


2

ดูเหมือนว่าตั้งแต่ XCode 7.xa มีคำเตือนจำนวนมากออกมาเมื่อเปิดใช้งานโมดูลเสียงดังกราวด้วย 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ประกาศว่าจะคอมไพเลอร์ในการโหลดprecompiledไบนารีของกรอบซึ่งลดเวลาอาคาร Modular Framework ประกอบด้วย.modulemap[เกี่ยวกับ]

หากเปิดใช้งานคุณลักษณะโมดูลในโครงการ Xcode #includeและ#importคำสั่งจะถูกแปลงโดยอัตโนมัติเพื่อให้@importเกิดประโยชน์ทั้งหมด

ป้อนคำอธิบายรูปภาพที่นี่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.