paint-brush
Cum să vă construiți proiectul Xcode pentru mai multe platforme din ecosistemul Applede@darrylbayliss
165 lecturi Noua istorie

Cum să vă construiți proiectul Xcode pentru mai multe platforme din ecosistemul Apple

de Darryl Bayliss9m2025/02/12
Read on Terminal Reader

Prea lung; A citi

Aflați cum să vă construiți proiectul Xcode pentru mai multe platforme din ecosistemul Apple.
featured image - Cum să vă construiți proiectul Xcode pentru mai multe platforme din ecosistemul Apple
Darryl Bayliss HackerNoon profile picture
0-item
1-item

Î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ă Christmas Chill , ceva pe care l-am construit 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.


Î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 UIViewRepresentable . Un API grozav care oferă interoperabilitate între UIKit și SwiftUI, dacă aveți vreodată nevoie.


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 React și Jetpack Compose . 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.


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 .xcodeproj , iar sub meniul drop-down Destinații acceptate , faceți clic pe butonul plus.


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.


Adăugați Apple Vision Pro Destination



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 .


Activați asistența pentru destinație


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 ImmersiveSpace , un API disponibil numai pentru visionOS.


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 blocurilor de compilare condiționată . Blocurile de compilare sunt secțiuni de cod care oferă instrucțiuni pentru când compilatorul ar trebui să compile codul în bloc.


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.


Blocuri de compilare condiționate

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 surselor de compilare și a resurselor pachetului de copiere 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 Build Phases din proiectul Xcode.


Faze de construcție


Compile Sources face munca grea de a compila codul sursă în codul mașinii. Fie că este Swift, Objective-C sau chiar C/C++.

Copiați resursele pachetului copiează toate resursele asociate pentru aplicația țintă în pachetul de aplicații . Un fel de container pentru tot codul și resursele aplicației, inclusiv imagini, videoclipuri, șiruri localizabile și multe altele.


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 unprotocol Swift pentru a furniza un contract care se așteaptă să fie îndeplinit de o structură sau o clasă.


 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 } }


TargetAppAContentManager este implementarea concretă utilizată pentru prima țintă a aplicației. Acesta oferă o serie de Content , care se referă la numele resurselor găsite în pachetul de aplicații pentru țintă.


 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ă TargetAppBContentManager , 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.


Cu ambele implementări create, acum vă puteți referi la ele indirect în codul dvs. setând tipul obiectului la ContentManager . Consultați exemplul ViewModel de mai jos:


 @Observable class VideoListViewModel { var contentManager: ContentManager init(contentManager: ContentManager) { self.contentManager = contentManager } }


ViewModel se așteaptă ca un tip de ContentManager să treacă prin inițializatorul său. ViewModel poate fi transmis de orice tip de ContentManager și poate continua să funcționeze conform așteptărilor. Aceasta înseamnă, de asemenea, că ViewModel poate fi reutilizat în ambele aplicații ținte.


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 TargetAppAContentMananger ca parte a surselor sale, iar aplicației B i se trece TargetAppBContentManager .


Adăugați Manager de conținut la faza de compilare a surselor de compilare

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 Copy Bundle Resources 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.


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ă ContentManager sunt stocate în pachet. Dacă testul eșuează atunci când este rulat, atunci știți că lipsește o resursă din pachet.

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:


  1. 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.


  2. Citiți îndrumările Apple privind introducerea aplicațiilor existente în visionOS . Oferă sfaturi și sugestii utile despre cum să o faci și cum să profiti de funcțiile visionOS.


  3. 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 un videoclip de la WWDC 2022 pe acest subiect.


  4. 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 Christmas Chill și Ocean Chill . 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!)