ในเดือนมิถุนายน 2023 เมื่อ Apple ประกาศเปิดตัว Vision Pro ฉันมีความคิดที่จะใช้งานได้ดีบนชุดหูฟัง ซึ่งเป็นคอลเลกชันวิดีโอที่เล่นวนซ้ำไปพร้อมกับการใช้งานประจำวันของคุณ ฉันมีแอปที่สามารถทำสิ่งนี้ได้อยู่แล้ว ชื่อว่า ซึ่งเป็นสิ่งที่ เมื่อ Apple TV เครื่องแรกที่รองรับ App Store วางจำหน่าย แอปนี้มีคอลเลกชันวิดีโอที่เล่นวนซ้ำซึ่งคุณสามารถใช้เป็นฉากหลังในเทศกาลได้ Christmas Chill ฉันสร้างขึ้น ทุกปีในช่วงฤดูหนาว ฉันจะใช้เวลาสองสามวันในการปรับปรุงโครงการ เพิ่มเนื้อหาใหม่ และปรับปรุงฐานโค้ด การเปลี่ยนแปลงครั้งใหญ่ครั้งหนึ่งที่เกิดขึ้นกับโครงการเกิดขึ้นในเดือนธันวาคม 2023 เมื่อ UI ถูกย้ายจาก UIKit และ Storyboards ไปยัง SwiftUI ส่วนใหญ่แล้วได้ย้ายข้อมูลไปแล้ว ฉันต้องการมุมมองที่รองรับ AVPlayer ซึ่งรวมอยู่ใน ซึ่งเป็น API ที่ยอดเยี่ยมที่ให้การทำงานร่วมกันระหว่าง UIKit และ SwiftUI หากคุณต้องการ UIViewRepresentable ฉันค่อนข้างลังเลที่จะย้ายข้อมูลเร็วกว่านี้ เนื่องจากฉันเข้าใจ Declarative UI และแนวคิดของมันเป็นอย่างดีจากงานอื่นๆ ที่ใช้ และ แต่สิ่งนั้นเปลี่ยนไปสำหรับฉันเมื่อ Apple แนะนำ Apple Vision Pro และรองรับ SwiftUI Christmas Chill เป็นโปรเจ็กต์ที่ดีที่ช่วยให้ความรู้ด้าน Apple Dev ของฉันทันสมัยอยู่เสมอ และฉันกระตือรือร้นที่จะได้รับประสบการณ์ในการขยายแอปไปยังอุปกรณ์ต่างๆ React Jetpack Compose เมื่อการโยกย้ายไปยัง SwiftUI for Christmas Chill ในปี 2023 เสร็จสิ้นแล้ว ฉันจึงตั้งเป้าที่จะเพิ่มการรองรับ Vision Pro ในปี 2024 ด้านล่างนี้คือขั้นตอนการดำเนินการและคำแนะนำของฉันหากคุณกำลังพยายามทำเช่นเดียวกันสำหรับแอปของคุณเอง การเพิ่มแพลตฟอร์มใหม่ ในการเริ่มต้น โปรเจ็กต์จะต้องสามารถสร้างสำหรับ Vision Pro เป็นจุดหมายปลายทางได้ ซึ่งการทำเช่นนี้เป็นเรื่องง่ายอย่างน่าประหลาดใจ! ใน Xcode ให้เลือกไฟล์ . จากนั้นคลิกปุ่มบวกภายใต้ .xcodeproj รายการดรอปดาวน์ปลายทางที่รองรับ เมนูแบบดรอปดาวน์ของแพลตฟอร์ม Apple ที่มีอยู่ทั้งหมดจะปรากฏขึ้น เลื่อนเมาส์ไปเหนือแพลตฟอร์มที่ต้องการเพื่อเพิ่มเป็นจุดหมายปลายทาง ในกรณีนี้คือ Apple Vision จากนั้นคลิก Apple Vision ในส่วนที่เพิ่งปรากฏขึ้น ป๊อปอัปขนาดเล็กจะปรากฏขึ้นเพื่อแจ้งให้คุณทราบถึงการเปลี่ยนแปลงที่ Xcode ต้องทำกับเป้าหมาย คลิกเปิด ใช้งาน ขั้นตอนต่อไปคือสร้างแอปโดยใช้โปรแกรมจำลอง visionOS หากคุณมี Vision Pro อยู่ในมือ คุณสามารถดูคำแนะนำเกี่ยวกับวิธีการติดตั้งลงในอุปกรณ์ของคุณ ได้ที่นี่ ระหว่างการคอมไพล์ Xcode อาจพบข้อผิดพลาดของคอมไพเลอร์ และ/หรือแอปอาจขัดข้อง ซึ่งถือเป็นเรื่องปกติและควรอดทนรอ จากจุดนี้ คุณต้องแก้ไขข้อผิดพลาดในโปรเจ็กต์ของคุณจนกว่าแอปจะคอมไพล์ได้และไม่ทำงานขัดข้องอีกต่อไป ในกรณีของฉัน ใช้เวลาประมาณ 30 นาที ซึ่งส่วนหนึ่งต้องขอบคุณการทำงานหนักในการย้ายแอปจาก UIKit ไปยัง SwiftUI ก่อนหน้านี้! บล็อกการรวบรวมแบบมีเงื่อนไข SwiftUI เป็นเฟรมเวิร์กแบบมัลติแพลตฟอร์ม ซึ่งหมายความว่าเพียงแค่คอมไพล์โค้ด SwiftUI สำหรับแพลตฟอร์มอื่น ก็จะเปลี่ยนรูปลักษณ์ของเฟรมเวิร์กได้ โดยคำนึงถึงรูปแบบของแพลตฟอร์มและวิธีการโต้ตอบต่างๆ แม้ว่าสิ่งนี้จะช่วยให้พัฒนาได้รวดเร็วขึ้น แต่คุณอาจต้องการควบคุมการแสดงผลของแอปและใช้ประโยชน์จากจุดแข็งของแต่ละแพลตฟอร์ม ตัวอย่างที่ดีคือความสามารถ Immersion ของ Vision Pro SwiftUI จัดเตรียม API สำหรับคุณสมบัตินี้ผ่าน ซึ่งเป็น API ที่มีให้เฉพาะใน visionOS เท่านั้น ImmersiveSpace หากคุณพยายามใช้ API นี้ในขณะคอมไพล์โปรเจ็กต์สำหรับ Apple TV, Xcode จะแสดงข้อผิดพลาดเพื่อแจ้งให้ทราบว่า API นี้ไม่พร้อมใช้งาน แล้วทางแก้ไขเพื่อหลีกเลี่ยงสถานการณ์ดังกล่าวคืออะไร คำตอบคือการใช้ Compilation Blocks คือส่วนของโค้ดที่ให้คำแนะนำว่าเมื่อใดคอมไพเลอร์จึงควรคอมไพล์โค้ดภายในบล็อค Conditional Compilation Blocks แม้ว่าจะรองรับเงื่อนไขต่างๆ มากมาย แต่สิ่งที่มีประโยชน์ที่สุดสำหรับความต้องการของเราคือการตรวจจับว่าโค้ดถูกคอมไพล์สำหรับแพลตฟอร์มใด คุณสามารถทำได้โดยใช้โค้ดเพียงไม่กี่บรรทัด: var body: some Scene { #if os(tvOS) WindowGroup { HStack { Text("I am running on tvOS!") } } #elseif os(visionOS) ImmersiveSpace(id: "MyImmersiveSpace") { } #endif } ฟีเจอร์ที่ดีอย่างหนึ่งที่ Xcode ทำเพื่อรองรับบล็อกการคอมไพล์แบบมีเงื่อนไขก็คือ การแสดงให้เห็นอย่างชัดเจนว่าโค้ดใดที่จะคอมไพล์ได้ขึ้นอยู่กับแพลตฟอร์มที่เลือกสำหรับการคอมไพล์ นอกจากนี้ Xcode ยังจะลดโค้ดที่ไม่ถูกคอมไพล์ลงเล็กน้อยด้วย การฉีดการอ้างอิงผ่านขั้นตอนการสร้าง เคล็ดลับที่มีประโยชน์อย่างหนึ่งที่ฉันพบคือการใช้ขั้นตอนการสร้าง และ เป็นรูปแบบหนึ่งของการฉีดการอ้างอิง กระบวนการเหล่านี้จะทำงานเมื่อสร้างแอปและสามารถพบได้ภายใต้แท็บ ใน Xcode Project Compile Sources Copy Bundle Resources Build Phases ทำหน้าที่คอมไพล์โค้ดต้นฉบับของคุณเป็นโค้ดเครื่อง ไม่ว่าจะเป็น Swift, Objective-C หรือแม้แต่ C/C++ Compile Sources คัดลอกทรัพยากรที่เกี่ยวข้องทั้งหมดสำหรับเป้าหมายแอปลงใน สำหรับโค้ดและทรัพยากรทั้งหมดของแอป รวมถึงรูปภาพ วิดีโอ สตริงที่แปลเป็นภาษาท้องถิ่นได้ และอื่นๆ Copy Bundle Resources App Bundle ซึ่งเป็นคอนเทนเนอร์ ขั้นตอนการสร้างทั้งสองขั้นตอนนี้ทำให้แอปมีความยืดหยุ่นมากขึ้น เนื่องจากแต่ละเป้าหมายใหม่จะมีขั้นตอนการสร้างของตัวเอง รวมถึงขั้นตอนสองขั้นตอนข้างต้น แอป Whitelabel ที่ให้ธุรกิจปรับแต่งเนื้อหาของตนเองใช้เทคนิคนี้ รวมถึงเทคนิคอื่นๆ ด้วย คุณอาจพบว่าคุณต้องการจัดเตรียมเนื้อหาที่แตกต่างกันสำหรับแอปของคุณเอง ขึ้นอยู่กับแพลตฟอร์มที่แอปนั้นทำงาน มาใช้ประโยชน์จากขั้นตอนการสร้างเหล่านี้โดยจัดเตรียมแหล่งเนื้อหาที่แตกต่างกันสองแหล่งเพื่อทำเช่นนั้น ก่อนอื่น ให้ใช้ เพื่อจัดทำสัญญาที่คาดว่าจะได้รับการปฏิบัติตามโดยโครงสร้างหรือคลาส โปรโตคอล Swift protocol ContentManager { var content: [Content] { get } } ต่อไปมาดูตัวดำเนินการโปรโตคอล 2 ตัวกัน ตัวแรกคือ: class TargetAppAContentManager : ContentManager { var content: [Content] { return [ Content(name: TargetAppAContentIdentifier.videoOneName.rawValue, image: TargetAppAImagePreviewIdentifier.videoOnePreview.rawValue, video: TargetAppAImageVideoIdentifier.videoOneVideo.rawValue), Content(name: TargetAppAContentIdentifier.videoTwoName.rawValue, image: TargetAppAImagePreviewIdentifier.videoTwoPreview.rawValue, video: TargetAppAImageVideoIdentifier.videoTwoVideo.rawValue), Content(name: TargetAppAContentIdentifier.videoThreeName.rawValue, image: TargetAppAImagePreviewIdentifier.videoThreePreview.rawValue, video: TargetAppAImageVideoIdentifier.videoThreeVideo.rawValue), ] return contentToShow } } คือการใช้งานจริงที่ใช้ได้กับเป้าหมายแอปแรก โดยจัดเตรียมอาร์เรย์ของ ซึ่งอ้างอิงถึงชื่อทรัพยากรที่พบในชุดแอปสำหรับเป้าหมาย TargetAppAContentManager Content class TargetAppBContentManager : ContentManager { var content: [Content] { return [ Content(name: TargetAppBContentIdentifier.videoOneName.rawValue, image: TargetAppBImagePreviewIdentifier.videoOnePreview.rawValue, video: TargetAppBImageVideoIdentifier.videoOneVideo.rawValue), Content(name: TargetAppBContentIdentifier.videoTwoName.rawValue, image: TargetAppBImagePreviewIdentifier.videoTwoPreview.rawValue, video: TargetAppBImageVideoIdentifier.videoTwoVideo.rawValue), Content(name: TargetAppBContentIdentifier.videoThreeName.rawValue, image: TargetAppBImagePreviewIdentifier.videoThreePreview.rawValue, video: TargetAppBImageVideoIdentifier.videoThreeVideo.rawValue), ] } } ถัดไปคือ ซึ่งเป็นการใช้งานจริงสำหรับเป้าหมายแอปที่สอง ดูคล้ายกับการใช้งานครั้งแรกมาก ยกเว้นว่าตัวระบุของแอป B จะแตกต่างกัน TargetAppBContentManager เมื่อสร้างการใช้งานทั้งสองแบบแล้ว ตอนนี้คุณสามารถอ้างถึงการใช้งานทั้งสองแบบโดยอ้อมในโค้ดของคุณได้โดยกำหนดประเภทของอ็อบเจ็กต์เป็น ลองดูตัวอย่าง ViewModel ด้านล่าง: ContentManager @Observable class VideoListViewModel { var contentManager: ContentManager init(contentManager: ContentManager) { self.contentManager = contentManager } } ViewModel คาดหวังให้ ชนิดหนึ่งส่งผ่านตัวเริ่มต้น ViewModel สามารถส่งผ่าน ชนิดหนึ่งได้และยังคงทำงานตามที่คาดหวัง ซึ่งหมายความว่า ViewModel สามารถนำมาใช้ซ้ำในเป้าหมายแอปทั้งสองได้ ContentManager ContentManager สิ่งสุดท้ายที่ต้องทำคือตรวจสอบให้แน่ใจว่าได้เพิ่ม ContentManager ที่ถูกต้องลงในขั้นตอนการคอมไพล์แหล่งที่มา ในกรณีนี้ แอป A จะถูกส่งต่อ เป็นส่วนหนึ่งของแหล่งที่มา และแอป B จะถูกส่งต่อ TargetAppAContentMananger TargetAppBContentManager การเพิ่มทรัพยากร App Bundle สิ่งสุดท้ายที่เหลือที่ต้องทำคือตรวจสอบให้แน่ใจว่าแต่ละ App Bundle มีทรัพยากรที่มีชื่อตรงกับตัวระบุที่ใช้โดยแอป วิธีง่ายๆ คือตรวจสอบขั้นตอนการสร้าง ของเป้าหมายแอปแต่ละรายการและตรวจสอบให้แน่ใจว่าทรัพยากรได้รับการอ้างอิงโดยผู้จัดการเนื้อหา หากไม่เป็นเช่นนั้น ให้ลากทรัพยากรเหล่านั้นจากโปรเจ็กต์ Xcode ของคุณไปยังขั้นตอนคัดลอกทรัพยากร Copy Bundle Resources การทดสอบนี้ต้องใช้เวลาและความระมัดระวังเล็กน้อย เนื่องจากคุณจะไม่ได้รับข้อผิดพลาดขณะคอมไพล์หากทรัพยากรที่อ้างถึงไม่มีอยู่ในบันเดิล ในระหว่างรันไทม์ คุณจะพบกับข้อผิดพลาด! วิธีที่ดีในการทำให้การตรวจสอบเป็นแบบอัตโนมัติคือการเขียนการทดสอบยูนิตเพื่อยืนยันว่าทรัพยากรทั้งหมดที่ อ้างอิงถึงนั้นถูกเก็บไว้ในชุดข้อมูล หากการทดสอบล้มเหลวเมื่อเรียกใช้ แสดงว่าคุณมีทรัพยากรที่ขาดหายไปในชุดข้อมูล ContentManager จะไปที่ไหนต่อไป? หากคุณมาถึงจุดนี้แล้ว คุณน่าจะมีแนวคิดที่ดีว่าจะนำแอปของคุณไปยังแพลตฟอร์มอื่นๆ ของ Apple ได้อย่างไร เพื่อสรุปโพสต์นี้ ฉันจะฝากเคล็ดลับและทรัพยากรสองสามอย่างที่ฉันแนะนำ: หากจะเพิ่มการรองรับ Apple Vision ให้กับแอปที่มีอยู่ ก่อนอื่น ให้ย้ายโค้ดของคุณจาก UIKit ไปยัง SwiftUI ให้ได้มากที่สุด เมื่อได้เห็นความเร็วของแอปที่มีอยู่ที่ทำงานบน Vision Pro เมื่อย้ายไปยัง SwiftUI แล้ว แสดงว่าการพึ่งพาสิ่งนี้ได้นั้นมีประโยชน์ อ่านคำแนะนำของ Apple เกี่ยวกับ ซึ่งให้คำแนะนำและข้อเสนอแนะที่มีประโยชน์เกี่ยวกับวิธีการดำเนินการดังกล่าวและการใช้ประโยชน์จากคุณสมบัติของ visionOS การนำแอปที่มีอยู่มาสู่ visionOS หากคุณกำลังคิดที่จะเริ่มต้นสร้างแอปมัลติแพลตฟอร์มใหม่ด้วยตัวเอง Xcode มีแท็บมัลติแพลตฟอร์ม ซึ่งมีเทมเพลตแอปให้เลือกใช้มากมาย นอกจากนี้ยังมี เกี่ยวกับหัวข้อนี้ด้วย วิดีโอจาก WWDC 2022 หากคุณต้องการดูตัวอย่างแอปที่ใช้งานบนแพลตฟอร์มต่างๆ ขอแนะนำให้ลองดูแอปส่วนตัวของฉัน และ แอปทั้งสองนี้สามารถใช้งานบน tvOS และ Vision Pro ได้ โดยสร้างขึ้นจากโค้ดฐานเดียว (เร็วๆ นี้ tvOS จะรองรับ Ocean Chill!) Christmas Chill Ocean Chill