În iunie 2023, când Apple a anunțat Vision Pro, am avut o idee care ar putea funcționa bine pe setul cu cască - o colecție de videoclipuri în buclă redate împreună cu utilizarea de zi cu zi. Aveam deja o aplicație care ar putea face acest lucru, numită , ceva pe care când a fost disponibil primul Apple TV care acceptă un App Store. Include o colecție de videoclipuri în buclă pe care le puteți folosi ca fundal festiv. Christmas Chill l-am construit În fiecare an, peste iarnă, petrec câteva zile îmbunătățindu-l, adăugând conținut nou și îmbunătățind baza de cod. Una dintre cele mai mari modificări aduse proiectului a avut loc în decembrie 2023, când interfața de utilizare a fost migrată de la UIKit și Storyboards la SwiftUI. Ei bine, în mare parte au migrat. Aveam nevoie de o vizualizare susținută de AVPlayer înfășurată într-un . Un API grozav care oferă interoperabilitate între UIKit și SwiftUI, dacă aveți vreodată nevoie. UIViewRepresentable Am fost oarecum ezitant să migrez mai devreme, deoarece aveam o bună înțelegere a Declarative UI și a conceptelor sale din alte lucrări cu și . Acest lucru s-a schimbat pentru mine odată cu introducerea de către Apple a Apple Vision Pro și suportul acestuia pentru SwiftUI. Christmas Chill a fost un proiect frumos pentru a-mi menține la zi cunoștințele despre Apple Dev și am fost dornic să câștig experiență în extinderea aplicației pe diferite dispozitive. React Jetpack Compose Odată ce migrarea din 2023 la SwiftUI pentru Christmas Chill a fost finalizată, mi-am propus în 2024 să adaug suport pentru Vision Pro. Mai jos este cum am procedat și ce vă recomand dacă încercați să faceți același lucru pentru propriile aplicații. Adăugarea unei noi platforme Pentru a începe, proiectul trebuie să poată fi construit pentru Vision Pro ca destinație; a face acest lucru este surprinzător de ușor! În interiorul Xcode, selectați fișierul , iar sub meniul drop-down , faceți clic pe butonul plus. .xcodeproj Destinații acceptate Apare un meniu drop-down cu toate platformele Apple disponibile. Plasați cursorul peste platforma dorită pentru a adăuga ca destinație, în acest caz, Apple Vision, apoi faceți clic pe Apple Vision în secțiunea care apare recent. Va apărea o mică fereastră pop-up pentru a vă informa despre modificările pe care Xcode trebuie să le facă țintei. Faceți clic . pe Activare Apoi, construiți aplicația folosind simulatorul visionOS. Dacă aveți un Vision Pro la îndemână, puteți găsi instrucțiuni despre cum să îl instalați pe dispozitivul dvs. . aici În timpul compilării, este probabil că Xcode va găsi erori de compilator și/sau aplicația se va bloca. Acest lucru este de așteptat și o practică de a avea răbdare. Din acest punct, trebuie să remediați erorile din proiectul dvs. până când aplicația se compila și nu se mai blochează. În cazul meu, acest lucru a durat aproximativ 30 de minute, parțial datorită muncii grele de a migra aplicația de la UIKit la SwiftUI anterior! Blocuri de compilare condiționate SwiftUI, în esență, este un cadru multiplatformă, adică doar prin compilarea codului SwiftUI pentru o altă platformă, își va modifica aspectul. Luând în considerare stilul platformei și diferitele metode de interacțiune. Deși acest lucru vă ajută să faceți progrese rapide în timpul dezvoltării, este posibil să doriți mai mult control asupra modului în care apare aplicația și să profitați de punctele forte ale fiecărei platforme individuale. Un bun exemplu sunt capabilitățile de imersie ale Vision Pro; SwiftUI oferă un API pentru aceasta prin , un API disponibil numai pentru visionOS. ImmersiveSpace Dacă ați încercat să utilizați acest API în timp ce compilați proiectul pentru Apple TV, Xcode va afișa o eroare care informează că acest API nu este disponibil. Deci, care este soluția pentru a evita această situație? Răspunsul vine din utilizarea . Blocurile de compilare sunt secțiuni de cod care oferă instrucțiuni pentru când compilatorul ar trebui să compile codul în bloc. blocurilor de compilare condiționată Deși acceptă o varietate de condiții, cel mai util pentru nevoile noastre este detectarea pentru ce platformă este compilat codul. Puteți face acest lucru cu doar câteva linii de cod: var body: some Scene { #if os(tvOS) WindowGroup { HStack { Text("I am running on tvOS!") } } #elseif os(visionOS) ImmersiveSpace(id: "MyImmersiveSpace") { } #endif } O caracteristică bună pe care Xcode o face pentru a sprijini blocurile de compilare condiționată este să clarifice ce cod va compila în funcție de platforma selectată pentru compilare. De asemenea, se va estompa ușor codul care nu va fi compilat. Injectarea dependenței prin fazele de construcție Unul dintre cele mai utile trucuri pe care le-am găsit este utilizarea fazelor de compilare a și ca o formă de injectare a dependenței. Aceste procese rulează atunci când aplicația este construită și pot fi găsite în fila din proiectul Xcode. surselor de compilare a resurselor pachetului de copiere Build Phases face munca grea de a compila codul sursă în codul mașinii. Fie că este Swift, Objective-C sau chiar C/C++. Compile Sources copiează toate resursele asociate pentru aplicația țintă în . Un pentru tot codul și resursele aplicației, inclusiv imagini, videoclipuri, șiruri localizabile și multe altele. Copiați resursele pachetului pachetul de aplicații fel de container Aceste două faze de construire oferă o mare flexibilitate aplicațiilor, deoarece fiecare țintă nouă oferă propriile faze de construcție, inclusiv cei doi pași de mai sus. Aplicațiile etichete albe care oferă companiilor o modalitate de a-și personaliza conținutul folosesc această tehnică, printre altele. Este posibil să descoperiți că doriți să furnizați conținut diferit pentru propriile aplicații, în funcție de platforma pe care rulează acestea. Să folosim aceste faze de construcție în avantajul nostru și să oferim două surse diferite de conținut pentru a face asta. În primul rând, să folosim un pentru a furniza un contract care se așteaptă să fie îndeplinit de o structură sau o clasă. protocol Swift protocol ContentManager { var content: [Content] { get } } În continuare, să aruncăm o privire la doi implementatori ai protocolului. Iată primul: 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 } } este implementarea concretă utilizată pentru prima țintă a aplicației. Acesta oferă o serie de , care se referă la numele resurselor găsite în pachetul de aplicații pentru țintă. 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), ] } } Urmează , implementarea concretă utilizată pentru a doua țintă a aplicației. Arată foarte asemănător cu prima implementare, cu excepția aplicației B, identificatorii sunt diferiți. TargetAppBContentManager Cu ambele implementări create, acum vă puteți referi la ele indirect în codul dvs. setând tipul obiectului la . Consultați exemplul ViewModel de mai jos: ContentManager @Observable class VideoListViewModel { var contentManager: ContentManager init(contentManager: ContentManager) { self.contentManager = contentManager } } ViewModel se așteaptă ca un tip de să treacă prin inițializatorul său. ViewModel poate fi transmis de orice tip de și poate continua să funcționeze conform așteptărilor. Aceasta înseamnă, de asemenea, că ViewModel poate fi reutilizat în ambele aplicații ținte. ContentManager ContentManager Ultimul lucru de făcut este să vă asigurați că ContentManagerul corect este adăugat la faza de compilare a surselor. În acest caz, aplicației A i se trece ca parte a surselor sale, iar aplicației B i se trece . TargetAppAContentMananger TargetAppBContentManager Adăugarea resurselor App Bundle Ultimul lucru care rămâne de făcut este să vă asigurați că fiecare pachet de aplicații conține resurse cu nume care se potrivesc cu identificatorii utilizați de aplicație. Modalitatea simplă este să verificați faza de compilare a pentru fiecare aplicație țintă și să vă asigurați că managerul de conținut face referire la resurse. Dacă nu, trageți-le din proiectul dvs. Xcode în faza de copiere a resurselor. Copy Bundle Resources Acest lucru necesită puțin timp și grijă pentru a testa, deoarece nu primiți o eroare de compilare dacă o resursă la care se face referire nu este disponibilă în pachet. În timpul rulării, veți avea un accident! O modalitate bună de a automatiza verificarea este să scrieți un test unitar pentru a confirma toate resursele la care se referă sunt stocate în pachet. Dacă testul eșuează atunci când este rulat, atunci știți că lipsește o resursă din pachet. ContentManager Unde să mergi mai departe? Dacă ați ajuns până aici, ar trebui să aveți o idee bună despre cum să vă aduceți aplicația pe alte platforme Apple. Pentru a completa această postare, vă voi lăsa cu câteva sfaturi și resurse pe care le recomand: Dacă adăugați suport Apple Vision la o aplicație existentă, mai întâi, migrați cât mai mult din codul dvs. de la UIKit la SwiftUI. După ce ați văzut viteza unei aplicații existente care funcționează pe Vision Pro atunci când ați migrat la SwiftUI, este util să vă puteți baza. Citiți îndrumările Apple privind . Oferă sfaturi și sugestii utile despre cum să o faci și cum să profiti de funcțiile visionOS. introducerea aplicațiilor existente în visionOS Dacă vă gândiți să începeți singur o nouă aplicație multiplatformă, există o filă Multiplatform disponibilă în Xcode, care oferă o serie de șabloane de aplicație de utilizat. Există și pe acest subiect. un videoclip de la WWDC 2022 Dacă doriți să vedeți exemple de aplicații care funcționează pe mai multe platforme, vă recomand să consultați aplicațiile mele personale și . Acestea sunt două aplicații care funcționează pe tvOS și Vision Pro, construite dintr-o singură bază de cod. (Suportul tvOS pentru Ocean Chill va veni în curând!) Christmas Chill Ocean Chill