PreviewProvider — το πρωτόκολλο SwiftUI που καθορίζει το σημείο εισόδου για τη δημιουργία προεπισκοπήσεων στο Xcode Canvas. Η υλοποίηση του πρωτοκόλλου επιτρέπει στον προγραμματιστή να βλέπει τη διεπαφή χωρίς να εκκινεί τον εξομοιωτή, επιταχύνοντας την επανάληψη στο στάδιο σχεδιασμού. Σύμφωνα με το Apple Developer Documentation (2026), το PreviewProvider είναι υποχρεωτικό για όλα τα SwiftUI View εάν το έργο χρησιμοποιεί Canvas — χωρίς αυτό το Canvas δεν εμφανίζει τη διεπαφή χρήστη. Μάθετε περισσότερα στο άρθρο για το SwiftUI.
Βασικά σημεία
PreviewProvider — το πρωτόκολλο SwiftUI που καθορίζει τη σύμβαση για τη δημιουργία περιεχομένου προεπισκόπησης στο Xcode Canvas. Το πρωτόκολλο περιέχει μία υποχρεωτική ιδιότητα: previews τύπου some View. Οποιαδήποτε τιμή επιστρέφεται από το previews εμφανίζεται στο Canvas ως διαδραστική προεπισκόπηση. Το PreviewProvider δεν απαιτεί κληρονομικότητα — αρκεί μια στατική υλοποίηση σε extension.
Αρχιτεκτονικά, το PreviewProvider δεν αποτελεί μέρος του SwiftUI runtime — είναι αποκλειστικά εργαλείο ανάπτυξης. Το πρωτόκολλο επισημαίνεται με το χαρακτηριστικό @available(iOS 13.0, *) και δεν μεταγλωττίζεται στην έκδοση release, καθώς το Xcode χρησιμοποιεί υπό όρους μεταγλώττιση για να εξαιρέσει τον κώδικα προεπισκόπησης από την παραγωγή. Αυτό σημαίνει ότι το PreviewProvider δεν επηρεάζει το μέγεθος του δυαδικού αρχείου και τις επιδόσεις της εφαρμογής.
Ιδιότητα previews — η μοναδική απαίτηση του PreviewProvider. Πρέπει να επιστρέφει οποιοδήποτε View: από ένα απλό Text έως μια σύνθετη ιεραρχία με Group και ForEach. Το Xcode αποδίδει το επιστρεφόμενο View στο Canvas, εφαρμόζοντας τις ρυθμίσεις συστήματος (θέμα, μέγεθος, γραμματοσειρά).
import SwiftUI
struct GreetingView: View {
let name: String
var body: some View {
Text("Γεια σας, \(name)!")
.padding()
}
}
// PreviewProvider — στατική υλοποίηση
struct GreetingView_Previews: PreviewProvider {
static var previews: some View {
GreetingView(name: "World")
}
}
Σύμβαση ονομασίας: Η Apple συνιστά την ονομασία της δομής προεπισκόπησης ως {ViewName}_Previews. Αυτό δεν είναι υποχρεωτική απαίτηση του μεταγλωττιστή, αλλά βελτιώνει την αναγνωσιμότητα και την πλοήγηση στο έργο. Το Xcode αντικαθιστά αυτόματα αυτό το πρότυπο κατά τη δημιουργία ενός νέου αρχείου SwiftUI.
Μηχανισμός λειτουργίας Το PreviewProvider βασίζεται στη στατική αποστολή: το Xcode μεταγλωττίζει το extension με το PreviewProvider μόνο για τη διαμόρφωση Debug και καλεί το previews κατά τη διαδικασία δημιουργίας του Canvas. Κάθε φορά που αλλάζει ο κώδικας, το Xcode μεταγλωττίζει εκ νέου μόνο τα τροποποιημένα PreviewProvider, εξασφαλίζοντας σχεδόν άμεση ενημέρωση της προεπισκόπησης.
Το SwiftUI δεν εγγυάται την ακριβή αντιστοίχιση της προεπισκόπησης με το τελικό UI στον εξομοιωτή ή τη συσκευή — το Canvas χρησιμοποιεί απλοποιημένη απόδοση. Οι κινούμενες εικόνες με καθυστερήσεις ενδέχεται να εμφανίζονται λανθασμένα και ορισμένα στοιχεία UIKit (MapKit, WebView) δεν αποδίδονται στο Canvas χωρίς πρόσθετη ρύθμιση.
Το Group επιτρέπει την ταυτόχρονη εμφάνιση πολλών καταστάσεων ενός View, επιταχύνοντας την επανάληψη κατά το σχεδιασμό διαφορετικών διαμορφώσεων. Κάθε προεπισκόπηση εντός του Group αποδίδεται ανεξάρτητα.
struct ButtonView_Previews: PreviewProvider {
static var previews: some View {
Group {
ButtonView(title: "Primary", style: .primary)
.previewDisplayName("Primary")
ButtonView(title: "Disabled", style: .primary)
.disabled(true)
.previewDisplayName("Disabled")
ButtonView(title: "Secondary", style: .secondary)
.previewDisplayName("Secondary")
}
}
}
Το previewDisplayName προσθέτει ετικέτα σε κάθε προεπισκόπηση στο Canvas, κάτι που είναι ιδιαίτερα χρήσιμο κατά τη σύγκριση πολλών καταστάσεων. Ο μέγιστος αριθμός προεπισκοπήσεων στο Group δεν είναι περιορισμένος, αλλά περισσότερες από 6–8 επιβραδύνουν το Canvas.
Το Xcode παρέχει αρκετούς τροποποιητές για τη διαμόρφωση της εμφάνισης της προεπισκόπησης. Οι κύριοι: previewDevice — εξομοιώνει μια συγκεκριμένη συσκευή (iPhone 16 Pro, iPad Air, Apple Watch Ultra), previewLayout — ορίζει το μέγεθος (device, fixed, sizeThatFits). Ο συνδυασμός αυτών των τροποποιητών δίνει πλήρη έλεγχο στο περιβάλλον προεπισκόπησης.
Το previewDevice δέχεται μια συμβολοσειρά με το όνομα της συσκευής, για παράδειγμα “iPhone 16 Pro” ή “iPad Pro 13-inch (M4)”. Η λίστα των διαθέσιμων συσκευών εξαρτάται από τους εγκατεστημένους εξομοιωτές στο Xcode. Εάν η συσκευή δεν βρεθεί, το Canvas εμφανίζει την προεπισκόπηση στην προεπιλεγμένη συσκευή χωρίς σφάλμα.
| Τροποποιητής | Περιγραφή | Παράδειγμα |
|---|---|---|
| previewDevice | Εξομοίωση συσκευής | .previewDevice(“iPhone 16 Pro”) |
| previewLayout | Λειτουργία μεγέθους | .previewLayout(.sizeThatFits) |
| previewDisplayName | Ετικέτα προεπισκόπησης | .previewDisplayName(“Dark Mode”) |
| preferredColorScheme | Θέμα σχεδίασης | .preferredColorScheme(.dark) |
| dynamicTypeSize | Μέγεθος γραμματοσειράς | .dynamicTypeSize(.xxxLarge) |
Συνήθης πρακτική — εμφάνιση ενός View σε πολλές συσκευές ταυτόχρονα για έλεγχο της προσαρμοστικότητας. Για αυτό χρησιμοποιείται το ForEach με μια συστοιχία ονομάτων συσκευών.
struct AdaptiveView_Previews: PreviewProvider {
static var previews: some View {
ForEach(["iPhone SE (3rd generation)", "iPhone 16 Pro Max", "iPad Pro 13-inch (M4)"], id: \.self) { device in
AdaptiveView()
.previewDevice(.previewDevice(device))
.previewDisplayName(device)
}
}
}
Πρακτικά παραδείγματα δείχνουν διάφορα σενάρια χρήσης του PreviewProvider: από απλή προεπισκόπηση έως σύνθετες διαμορφώσεις με ζωντανά δεδομένα και συμβατότητα UIKit.
Ψευδοδεδομένα — το τυπικό μοτίβο για προεπισκόπηση όταν το View δέχεται ένα μοντέλο. Αντί για πραγματικό API, υποκαθίστανται δεδομένα δοκιμής, επιτρέποντας τον οπτικό έλεγχο της κατάστασης UI χωρίς εκκίνηση της εφαρμογής.
struct UserProfileView: View {
let user: User
var body: some View {
VStack {
AsyncImage(url: user.avatarURL)
.clipShape(Circle())
Text(user.name)
.font(.title)
Text(user.bio)
.font(.body)
.foregroundColor(.secondary)
}
}
}
struct UserProfileView_Previews: PreviewProvider {
static var previews: some View {
UserProfileView(user: .mock)
.previewDisplayName("Profile")
UserProfileView(user: .mockLongName)
.previewDisplayName("Long Name")
}
}
Συμβατότητα UIKit — το PreviewProvider λειτουργεί και με στοιχεία UIKit τυλιγμένα σε UIViewRepresentable. Αυτό επιτρέπει την προεπισκόπηση υπαρχόντων προβολών UIKit στο SwiftUI Canvas χωρίς μετεγκατάσταση ολόκληρου του έργου.
struct MapViewRepresentable: UIViewRepresentable {
func makeUIView(context: Context) -> MKMapView {
MKMapView()
}
func updateUIView(_ uiView: MKMapView, context: Context) {
// Διαμόρφωση χάρτη
}
}
struct MapView_Previews: PreviewProvider {
static var previews: some View {
MapViewRepresentable()
}
}
Το Canvas — είναι ο οπτικός επεξεργαστής του Xcode που αποδίδει το αποτέλεσμα του PreviewProvider σε πραγματικό χρόνο. Χωρίς υλοποίηση του PreviewProvider, το Canvas παραμένει κενό. Το Canvas και το PreviewProvider λειτουργούν ως ζεύγος: το PreviewProvider καθορίζει τι θα εμφανιστεί, το Canvas — πού και πώς.
Είναι σημαντικό να κατανοήσετε: Το Canvas — είναι το περιβάλλον εκτέλεσης της προεπισκόπησης, όχι μια εναλλακτική λύση για το PreviewProvider. Ακόμη κι αν ο προγραμματιστής δεν ανοίξει το Canvas, το PreviewProvider μπορεί να χρησιμοποιηθεί για γρήγορο έλεγχο κώδικα μέσω της προεπισκόπησης που εμφανίζεται όταν το ποντίκι τοποθετηθεί πάνω από το εικονίδιο του Canvas. Σύμφωνα με το WWDC 2024, η Apple συνιστά τη σύνταξη PreviewProvider για κάθε View ως πρότυπο ανάπτυξης, παρόμοια με τη σύνταξη unit tests.
| Στοιχείο | Ρόλος | Υποχρεωτικότητα |
|---|---|---|
| PreviewProvider | Καθορίζει το περιεχόμενο προεπισκόπησης | Υποχρεωτικό για Canvas |
| Canvas | Αποδίδει την προεπισκόπηση στον επεξεργαστή | Προαιρετικό (μπορεί να χρησιμοποιηθεί .preview) |
| SwiftUI View | Στοιχείο UI | Υποχρεωτικό |
Σύσταση: γράψτε PreviewProvider για κάθε δημόσιο View στο έργο. Αυτό επιταχύνει την ενσωμάτωση νέων προγραμματιστών, απλοποιεί τον έλεγχο κώδικα και επιτρέπει τον γρήγορο έλεγχο οπτικών αλλαγών χωρίς τη δημιουργία ολόκληρου του έργου.
Πρόβλημα 1: Η προεπισκόπηση δεν ενημερώνεται. Εάν το Canvas δεν αντικατοπτρίζει τις αλλαγές κώδικα, η αιτία είναι συνήθως η προσωρινή μνήμη DerivedData. Καθαρίστε το DerivedData μέσω Product → Clean Build Folder (⇧⌘K) ή διαγράφοντας χειροκίνητα το φάκελο ~/Library/Developer/Xcode/DerivedData. Μετά τον καθαρισμό, το Canvas ξαναχτίζει την προεπισκόπηση από την αρχή.
Πρόβλημα 2: Το PreviewProvider δεν βλέπει το @StateObject. Το PreviewProvider δημιουργεί ένα στατικό στιγμιότυπο του View, επομένως οι εξαρτήσεις που απαιτούν έγχυση (ViewModel, υπηρεσίες) πρέπει να μεταβιβάζονται μέσω αρχικοποιητή ή @StateObject με προεπιλεγμένη τιμή. Χρησιμοποιήστε ψευδο-αντικείμενα αντί για πραγματικές υπηρεσίες στην προεπισκόπηση.
Πρόβλημα 3: Οι κινήσεις δεν λειτουργούν στο Canvas. Το Canvas δεν υποστηρίζει όλες τις κινήσεις SwiftUI — ιδιαίτερα αυτές που εξαρτώνται από τον χρόνο (withAnimation με καθυστέρηση, .spring). Για έλεγχο κινήσεων, εκτελέστε την εφαρμογή στον εξομοιωτή. Το Canvas είναι κατάλληλο για στατικό έλεγχο διάταξης.
Έγχυση εξαρτήσεων — ο καλύτερος τρόπος για να λειτουργήσει το PreviewProvider με σύνθετα ViewModel. Δημιουργήστε ένα ξεχωριστό στιγμιότυπο ViewModel με δεδομένα δοκιμής και μεταβιβάστε το στον αρχικοποιητή του View.
struct DashboardView: View {
@StateObject var viewModel: DashboardViewModel
var body: some View {
List(viewModel.items) { item in
Text(item.title)
}
}
}
struct DashboardView_Previews: PreviewProvider {
static var previews: some View {
DashboardView(viewModel: DashboardViewModel.mock)
}
}
Επεκτάσεις ψευδοδεδομένων: δημιουργήστε ένα extension για το ViewModel που παρέχει στατικά .mock στιγμιότυπα. Αυτό διατηρεί τα δεδομένα δοκιμής κοντά στο ViewModel και καθιστά το PreviewProvider αναγνώσιμο.
Συχνές Ερωτήσεις
Τεχνικά όχι — η εφαρμογή θα μεταγλωττιστεί και χωρίς PreviewProvider. Ωστόσο, στην πράξη η Apple και η κοινότητα SwiftUI συνιστούν τη σύνταξη προεπισκόπησης για κάθε δημόσιο View. Το PreviewProvider επιταχύνει την ανάπτυξη, επιτρέπει τον γρήγορο έλεγχο διάταξης σε διαφορετικές συσκευές και χρησιμεύει ως οπτική τεκμηρίωση για την ομάδα.
Το PreviewProvider προσθέτει κώδικα μόνο στο Debug build, επομένως σφάλματα μεταγλώττισης μπορεί να προκύψουν εάν στην προεπισκόπηση χρησιμοποιούνται τύποι που δεν είναι διαθέσιμοι στη διαμόρφωση release. Σφάλματα προκύπτουν επίσης κατά τη χρήση του @available με πλατφόρμες που δεν υποστηρίζουν Canvas ή όταν ξεπερνιέται το όριο πολυπλοκότητας της προεπισκόπησης.
Άμεσα — με κανέναν τρόπο, το PreviewProvider εκτελείται απομονωμένα. Χρησιμοποιήστε ψευδοδεδομένα: δημιουργήστε μια στατική επέκταση του μοντέλου με .mock στιγμιότυπα. Για View με @StateObject, μεταβιβάστε το ViewModel με δεδομένα δοκιμής μέσω αρχικοποιητή. Αυτό προσομοιώνει πραγματικά δεδομένα χωρίς αιτήματα δικτύου.
Όχι, το PreviewProvider δεν επηρεάζει το μέγεθος του δυαδικού αρχείου release. Το Xcode χρησιμοποιεί υπό όρους μεταγλώττιση (#if DEBUG / #if !RELEASE) για να εξαιρέσει τον κώδικα προεπισκόπησης από το release build. Ο κώδικας PreviewProvider υπάρχει μόνο στη διαμόρφωση Debug και δεν εισέρχεται στο build του App Store.
Ναι, το Xcode υποστηρίζει τον εντοπισμό σφαλμάτων προεπισκοπήσεων. Τοποθετήστε ένα breakpoint μέσα στο previews ή στον ίδιο τον κώδικα View και επιλέξτε Product → Preview → Debug Preview. Μετά από αυτό, το breakpoint θα ενεργοποιηθεί κατά την απόδοση του Canvas. Αυτό είναι χρήσιμο για την ανάλυση προβλημάτων διάταξης που είναι ορατά μόνο στην προεπισκόπηση.
Σύνοψη
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης