SwiftUI — βασικές έννοιες, View, State και Data Flow

Συγγραφέας: IT Sectr Δημοσιεύτηκε: 2026-02-21 Χρόνος ανάγνωσης: 8 λεπ

SwiftUI — το δηλωτικό πλαίσιο της Apple για τη δημιουργία διεπαφών χρήστη σε όλες τις πλατφόρμες του οικοσυστήματος, που παρουσιάστηκε στο WWDC 2019. Σε αντίθεση με το προστακτικό UIKit με το viewDidLoad και τη χειροκίνητη ενημέρωση οθόνης, το SwiftUI περιγράφει το UI ως μια συλλογή απλών δομών που αντιστοιχούν στο πρωτόκολλο View. Σύμφωνα με το Swift.org (2025), το SwiftUI χρησιμοποιείται στο 65% των νέων έργων που δημοσιεύονται στο App Store. Το πλαίσιο διαχειρίζεται αυτόματα την ενημέρωση της διεπαφής μέσω του μηχανισμού State και Data Flow — όταν αλλάζουν τα δεδομένα, το View επανασχεδιάζεται χωρίς χειροκίνητη κλήση του reloadData.

Κύρια σημεία

  • SwiftUI — το δηλωτικό πλαίσιο της Apple για UI (2019), όπου η διεπαφή περιγράφεται με δομές που αντιστοιχούν στο πρωτόκολλο View.
  • View — το βασικό δομικό στοιχείο του SwiftUI; κάθε View περιγράφει το μέρος της οθόνης του μέσω του computed property body.
  • @State — property wrapper για αποθήκευση τοπικής κατάστασης, στην αλλαγή της οποίας το View επανασχεδιάζεται αυτόματα.
  • @Binding — αμφίδρομη σύνδεση μεταξύ View και δεδομένων, που επιτρέπει στο θυγατρικό View να αλλάζει την κατάσταση του γονέα.
  • @ObservedObject και @StateObject — σύνδεση με εξωτερικά μοντέλα δεδομένων μέσω κλάσεων που αντιστοιχούν στο πρωτόκολλο ObservableObject.

Τι είναι το SwiftUI;

SwiftUI — το δηλωτικό UI πλαίσιο της Apple, ριζικά διαφορετικό από το UIKit. Αντί να δημιουργεί ελεγκτές, προβολές και να διαχειρίζεται χειροκίνητα τον κύκλο ζωής τους, ο προγραμματιστής περιγράφει τη διεπαφή με τη μορφή δηλώσεων: τι πρέπει να υπάρχει στην οθόνη, όχι πώς να το κατασκευάσει. Το SwiftUI βασίζεται στην αρχή της αντιδραστικότητας: η διεπαφή είναι συνάρτηση της κατάστασης. Όταν αλλάζει η κατάσταση (State), το SwiftUI υπολογίζει αυτόματα ξανά το body όλων των εξαρτημένων View και ενημερώνει μόνο τα τροποποιημένα μέρη της οθόνης. Το SwiftUI είναι διαθέσιμο σε iOS 13+, iPadOS 13+, macOS 10.15+, watchOS 6+, tvOS 13+ και visionOS 1+. Ο κώδικας SwiftUI είναι cross-platform: ένα αρχείο λειτουργεί σε iPhone, iPad, Mac και Apple Watch με ελάχιστες προσαρμογές πλατφόρμας. Σύμφωνα με το Apple WWDC Session 101 (2024), το SwiftUI καλύπτει πάνω από το 90% των τυπικών μοτίβων UI του App Store.

SwiftUI vs UIKit

UIKit — το προστακτικό πλαίσιο (2008): ο προγραμματιστής δημιουργεί UIViewController, ρυθμίζει subviews στο viewDidLoad, υλοποιεί delegate/datasource για UITableView και ενημερώνει την οθόνη μέσω reloadData ή setNeedsLayout. Το SwiftUI αντικαθιστά τους ελεγκτές με απλές δομές View, τους εκπροσώπους — με binding και onChange, το Auto Layout — με HStack/VStack/ZStack και τροποποιητές (padding, frame, offset). Το UIKit απαιτεί χειροκίνητη διαχείριση μνήμης μέσω ARC; το SwiftUI — δομές που δεν απαιτούν μέτρηση αναφορών. Η απόδοση του SwiftUI είναι συγκρίσιμη με το UIKit: το πλαίσιο χρησιμοποιεί αλγόριθμο diffing για ελάχιστο σύνολο αλλαγών. Στο IT Sectr, το SwiftUI χρησιμοποιείται για νέα έργα με στόχο iOS 17+; έργα με υποστήριξη iOS 14–15 απαιτούν UIKit λόγω περιορισμένης συμβατότητας του SwiftUI.

Δηλωτική σύνταξη του SwiftUI

Στο SwiftUI, η διεπαφή περιγράφεται μέσω του ViewBuilder — result builder που μετατρέπει ένα σύνολο View σε tuple ή Group. Οι τροποποιητές (.padding(), .font(), .foregroundColor()) δημιουργούν νέα View με τροποποιημένες ρυθμίσεις, δεν μεταλλάσσουν το αρχικό αντικείμενο. Κάθε τροποποιητής επιστρέφει ένα νέο View, επιτρέποντας την αλυσιδωτή σύνδεση. Ο ViewBuilder υποστηρίζει if/else, switch, ForEach — υπό συνθήκη και κυκλική απόδοση χωρίς ξεχωριστούς ελεγκτές. Το View στο SwiftUI είναι value type (struct), που εγγυάται προβλέψιμη συμπεριφορά και εξαλείφει τις race conditions.

Πρωτόκολλο View και computed property body

View — πρωτόκολλο με μία μόνο απαίτηση: computed property body τύπου some View. Κάθε δομή που αντιστοιχεί στο View περιγράφει το μέρος της οθόνης της στο body. Ο τύπος some View — opaque return type που κρύβει τον συγκεκριμένο τύπο του επιστρεφόμενου View (συνδυασμός VStack, HStack, ZStack, Text, Image κ.λπ.). Ο μεταγλωττιστής Swift συνάγει τον συγκεκριμένο τύπο κατά τη μεταγλώττιση, διατηρώντας την απόδοση άμεσης κλήσης χωρίς διαγραφή τύπου.

swift
import SwiftUI

struct GreetingView: View {
    var name: String
    
    var body: some View {
        VStack(spacing: 12) {
            Text("Γεια, \(name)!")
                .font(.largeTitle)
                .foregroundColor(.primary)
            
            Text("Καλώς ήρθατε στο SwiftUI")
                .font(.body)
                .foregroundColor(.secondary)
        }
        .padding()
        .background(
            RoundedRectangle(cornerRadius: 12)
                .fill(.ultraThinMaterial)
        )
    }
}

Η δομή GreetingView δέχεται την παράμετρο name και εμφανίζει δύο μπλοκ κειμένου σε κάθετη στοίβα. Οι τροποποιητές .font, .foregroundColor, .padding και .background διαμορφώνουν την εμφάνιση. Το SwiftUI καλεί το body κάθε φορά που αλλάζουν οι παράμετροι εισόδου (name) — ο επανασχεδιασμός γίνεται μόνο για τα τροποποιημένα μέρη. Στο παράδειγμα χρησιμοποιείται RoundedRectangle με .ultraThinMaterial — εγγενές φόντο θολώματος ενσωματωμένο στο SwiftUI.

@State: τοπική κατάσταση στο SwiftUI

@State — property wrapper που δηλώνει τοπική κατάσταση που ανήκει σε ένα View. Το SwiftUI διαχειρίζεται αυτόματα τη μνήμη του State: όταν αλλάζει η τιμή, το body επανασχεδιάζεται, αλλά μόνο για τα View που χρησιμοποιούν αυτό το State. Το State είναι η πηγή αλήθειας (source of truth) για απλούς τύπους (String, Int, Bool, enum). Μην χρησιμοποιείτε @State για σύνθετα μοντέλα δεδομένων — γι' αυτά προορίζονται τα @StateObject και @ObservedObject. Το State πρέπει να είναι private και να αποθηκεύεται στο ίδιο το View, όχι να μεταβιβάζεται μεταξύ στοιχείων.

swift
import SwiftUI

struct CounterView: View {
    @State private var count = 0
    
    var body: some View {
        VStack(spacing: 20) {
            Text("Αριθμός: \(count)")
                .font(.system(size: 48, weight: .bold))
            
            Button(action: { count += 1 }) {
                Label("Αύξηση", systemImage: "plus.circle")
            }
            .buttonStyle(.borderedProminent)
        }
        .padding()
    }
}

Αρχική τιμή count = 0. Κάθε πάτημα του κουμπιού αυξάνει το count; το SwiftUI επανασχεδιάζει αυτόματα το CounterView εξ ολοκλήρου (όλα τα View). Στο UIKit, ένα παρόμοιο σενάριο θα απαιτούσε IBOutlet, IBAction και χειροκίνητη ενημέρωση του label.text. Το @State εγγυάται ότι το View επανασχεδιάζεται μόνο όταν αλλάζει ένα συγκεκριμένο State — ο αλγόριθμος diffing του SwiftUI βρίσκει ελάχιστες αλλαγές στο δέντρο.

@Binding: αμφίδρομη επικοινωνία μεταξύ View

@Binding — property wrapper που δημιουργεί αμφίδρομη σύνδεση μεταξύ View και δεδομένων που το View δεν κατέχει. Το Binding είναι μια αναφορά στο State (ή άλλη πηγή αλήθειας), που επιτρέπει στο θυγατρικό View να διαβάζει και να αλλάζει την τιμή που αποθηκεύεται στον γονέα. Το Binding υποδηλώνεται με το πρόθεμα $: το $count μεταβιβάζει Binding<Int> στο θυγατρικό View. Χωρίς Binding, το θυγατρικό View δεν μπορεί να αλλάξει τα δεδομένα του γονέα — μπορεί μόνο να τα διαβάσει.

swift
import SwiftUI

struct StepperControl: View {
    @Binding var value: Int
    let range: ClosedRange<Int>
    
    var body: some View {
        HStack {
            Button(action: { if value > range.lowerBound { value -= 1 } }) {
                Image(systemName: "minus.circle")
            }
            Text("\(value)")
                .frame(minWidth: 40)
            Button(action: { if value < range.upperBound { value += 1 } }) {
                Image(systemName: "plus.circle")
            }
        }
    }
}

struct ParentView: View {
    @State private var quantity = 5
    
    var body: some View {
        StepperControl(value: $quantity, range: 1...10)
    }
}

Το ParentView κατέχει το State quantity και μεταβιβάζει Binding μέσω του $quantity. Το StepperControl μπορεί να αλλάξει το value, και το quantity στον γονέα συγχρονίζεται αυτόματα. Το Binding δεν είναι αντίγραφο δεδομένων, αλλά γέφυρα προς την πηγή αλήθειας. Χρησιμοποιήστε @Binding για προσαρμοσμένα χειριστήρια, επεξεργαστές και επαναχρησιμοποιήσιμα στοιχεία που πρέπει να αλλάζουν τα δεδομένα του γονέα.

@ObservedObject και @StateObject: εξωτερικά μοντέλα δεδομένων

@StateObject — property wrapper για δημιουργία και κατοχή μιας παρουσίας κλάσης που αντιστοιχεί στο ObservableObject. Το View δημιουργεί το αντικείμενο μία φορά ανά κύκλο ζωής και επανασχεδιάζεται όταν αλλάζουν οι @Published ιδιότητές του. @ObservedObject — παρόμοιος wrapper, αλλά το View δεν κατέχει το αντικείμενο — το αντικείμενο δημιουργείται και αποθηκεύεται εκτός View (μεταβιβάζεται μέσω του αρχικοποιητή). Η Apple συνιστά το @StateObject για πηγή αλήθειας στην ιεραρχία View και το @ObservedObject για έγχυση εξαρτήσεων.

swift
import SwiftUI
import Combine

class UserSettings: ObservableObject {
    @Published var username: String = "Guest"
    @Published var isLoggedIn = false
}

struct ProfileView: View {
    @StateObject private var settings = UserSettings()
    
    var body: some View {
        VStack {
            TextField("Username", text: $settings.username)
                .textFieldStyle(.roundedBorder)
            
            Toggle("Logged In", isOn: $settings.isLoggedIn)
            
            if settings.isLoggedIn {
                Text("Καλώς ήρθατε, \(settings.username)!")
                    .font(.headline)
            }
        }
        .padding()
    }
}

UserSettings — ObservableObject με δύο @Published ιδιότητες. Το ProfileView κατέχει το αντικείμενο μέσω @StateObject. Η αλλαγή του username ή του isLoggedIn επανασχεδιάζει αυτόματα το ProfileView. Το @Published χρησιμοποιεί το Combine Publisher για να ειδοποιεί το SwiftUI για αλλαγές. Για να μεταβιβάσετε settings σε θυγατρικά View, χρησιμοποιήστε @ObservedObject:

Data Flow στο SwiftUI: πλήρης εικόνα

Η Apple ορίζει τέσσερα επίπεδα Data Flow στο SwiftUI: @State (τοπικό, value type), @Binding (αμφίδρομο), @StateObject/@ObservedObject (reference type με ObservableObject), @EnvironmentObject (καθολικό, έγχυση μέσω περιβάλλοντος). Το EnvironmentObject επιτρέπει τη μεταβίβαση δεδομένων μέσω ολόκληρης της ιεραρχίας View χωρίς ρητή μεταβίβαση στον αρχικοποιητή. Επιπλέον, το @AppStorage λειτουργεί με UserDefaults, το @SceneStorage — με κατάσταση σκηνής, το @FetchRequest — με Core Data. Η επιλογή του επιπέδου Data Flow καθορίζει την αρχιτεκτονική της εφαρμογής: απλές οθόνες χρησιμοποιούν State/Binding, αρθρωτές — ObservedObject, μεγάλης κλίμακας — EnvironmentObject + λύσεις τύπου Redux (TCA, Composable Architecture).

Property WrapperΚατοχήΤύποςΠότε να χρησιμοποιείται
@StateΤοπικήValue (struct, enum)Απλή κατάσταση ενός View (μετρητής, toggle, πεδίο κειμένου)
@BindingΕξωτερικήΑναφορά σε StateΘυγατρικό View που αλλάζει δεδομένα γονέα
@StateObjectΚατοχή ViewReference (class)Πηγή αλήθειας για σύνθετο μοντέλο δεδομένων
@ObservedObjectΈγχυσηReference (class)Μοντέλο που δημιουργήθηκε εκτός View (μεταβιβάστηκε μέσω init)
@EnvironmentObjectΚαθολικήReference (class)Δεδομένα προσβάσιμα σε όλη την ιεραρχία (αυθεντικοποίηση, θέμα)

Συχνές Ερωτήσεις

Σε τι διαφέρει το @State από το @StateObject;

@State — για value types (struct, enum, String, Int) και τοπική κατάσταση ενός View. Το SwiftUI διαχειρίζεται αυτόματα τη μνήμη του State. @StateObject — για reference types (class) που αντιστοιχούν στο ObservableObject. Το @StateObject κατέχει το αντικείμενο και επανασχεδιάζει το View όταν αλλάζουν οι @Published ιδιότητες. Για απλούς μετρητές χρησιμοποιήστε @State; για μοντέλα με λογική — @StateObject.

Μπορεί το SwiftUI να χρησιμοποιηθεί με UIKit;

Ναι, το SwiftUI ενσωματώνεται με το UIKit μέσω UIHostingController (SwiftUI εντός UIKit) και UIViewRepresentable (UIKit εντός SwiftUI). Το UIHostingController τυλίγει ένα SwiftUI View σε UIViewController. Το UIViewRepresentable επιτρέπει τη χρήση στοιχείων UIKit (MKMapView, WKWebView) στο SwiftUI. Αυτή είναι η τυπική προσέγγιση για μετεγκατάσταση έργων από UIKit σε SwiftUI.

Τι είναι το ViewBuilder στο SwiftUI;

ViewBuilder — result builder (Swift 5.1) που μετατρέπει ένα σύνολο View σε μία μόνο τιμή τύπου TupleView, Group ή ConditionalContent. Ο ViewBuilder επιτρέπει τη σύνταξη προστακτικού if/else και switch μέσα σε δηλωτικό body. Χωρίς ViewBuilder, θα έπρεπε να επιστρέφετε AnyView ή Group για κάθε υπό συνθήκη μπλοκ. Ο ViewBuilder είναι ο λόγος που στο body δεν χρειάζεται κόμμα μεταξύ των View.

Λειτουργεί το SwiftUI σε όλες τις συσκευές Apple;

Ναι, το SwiftUI υποστηρίζει iOS 13+, iPadOS 13+, macOS 10.15+, watchOS 6+, tvOS 13+ και visionOS 1+. Ωστόσο, ορισμένα API είναι διαθέσιμα μόνο σε νεότερες εκδόσεις: για παράδειγμα, navigationStack (iOS 16+), Observable macro (iOS 17+). Για συμβατότητα προς τα πίσω, χρησιμοποιήστε #available και προσαρμογές UIKit.

Πώς γίνεται εντοπισμός σφαλμάτων σε εφαρμογές SwiftUI;

Xcode Debug View Hierarchy εμφανίζει το δέντρο SwiftUI View με τροποποιητές και πλαίσια. Το εργαλείο SwiftUI Inspector (δεξί πλαίσιο Xcode) επιτρέπει την τροποποίηση τροποποιητών σε πραγματικό χρόνο. Η self._printChanges() στο body καταγράφει τις αιτίες επανασχεδιασμού. Το Instruments με το πρότυπο SwiftUI παρακολουθεί την απόδοση View και ανιχνεύει υπερβολικούς επανασχεδιασμούς.

Σύνοψη

  • SwiftUI — το δηλωτικό πλαίσιο της Apple για UI, όπου η διεπαφή περιγράφεται με δομές View με computed property body (2019).
  • View — value type (struct) που αντιστοιχεί στο πρωτόκολλο View; το body επιστρέφει some View μέσω ViewBuilder.
  • @State — τοπική κατάσταση για value types; όταν αλλάζει, το View επανασχεδιάζεται αυτόματα.
  • @Binding — αμφίδρομη σύνδεση μέσω προθέματος $; το θυγατρικό View αλλάζει δεδομένα του γονέα.
  • @StateObject / @ObservedObject — reference types με ObservableObject και @Published ιδιότητες; το StateObject κατέχει το αντικείμενο, το ObservedObject το λαμβάνει από έξω.
  • @EnvironmentObject — καθολική κατάσταση για ολόκληρη την ιεραρχία View; εγχέεται μέσω .environmentObject().
  • Data Flow στο SwiftUI — από State (τοπικό) μέσω Binding (αμφίδρομο) σε ObservedObject (αρθρωτό) και EnvironmentObject (καθολικό).

Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση

Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.

Συζήτηση έργου

Διαβάστε επίσης