viewWillAppear — είναι μια μέθοδος UIViewController την οποία το UIKit καλεί κάθε φορά πριν γίνει ορατή η οθόνη για τον χρήστη. Σύμφωνα με Apple Developer Documentation, αυτή η μέθοδος λαμβάνει μια boolean παράμετρο animated που δείχνει αν η μετάβαση γίνεται με εντόπισμό. viewWillAppear — είναι το κύριο σημείο για ενημέρωση δεδομένων και συγχρονισμό της κατάστασης της οθόνης.
Βασικά
viewWillAppear — είναι μια μέθοδος UIViewController την οποία το UIKit καλεί αμέσως πριν προσθέσει το View στην ιεραρχία παραθύρων. Σε αυτή τη στιγμή το View έχει ήδη τα τελικά μεγέθη μετά από τις διαδρομές Auto Layout, αλλά δεν είναι ακόμα ορατό για τον χρήστη — η εντόπισμένη μετάβαση είτε δεν έχει ξεκινήσει, είτε εκτελείται. Ο προγραμματιστής παρακάμπτει αυτή τη μέθοδο για να εκτελέσει λειτουργίες που πρέπει να συμβούν πριν από κάθε εμφάνιση της οθόνης.
Σε αντίθεση με το viewDidLoad που εκτελείται μία φορά, το viewWillAppear καλείται κάθε φορά που η οθόνη πρόκειται να εμφανιστεί: κατά το αρχικό άνοιγμα, κατά την επιστροφή από ένα θυγατρικό ελεγκτή, μετά το κλείσιμο ενός τροπικού παραθύρου και κατά την εναλλαγή καρτελών TabBar. Αυτό το καθιστά βασική μέθοδο για τη διατήρηση της ενημερωμένης κατάστασης της διαπαφής.
Η μέθοδος λαμβάνει την παράμετρο animated τύπου Bool, η οποία είναι true αν η εμφάνιση της οθόνης συνοδεύεται από εντόπισμό. Αυτή η παράμετρος είναι βολική να μεταβιβάζεται στις μεθόδους NavigationBar και TabBar που έχουν παρόμοια παράμετρο για συνεπή συμπεριφορά.
Χρονισμός της κλήσης viewWillAppear εξαρτάται από τον τύπο πλοήγησης, αλλά ο γενικός κανόνας είναι αμετάβλητος: η μέθοδος εκτελείται πριν γίνει ορατό το View. Ας εξετάσουμε τα κύρια σενάρια.
Μετά την κλήση viewDidLoad, το UIKit ξεκινά την προετοιμασία για εμφάνιση: το View προστίθεται στην ιεραρχία, εκτελούνται οι διαδρομές layout, και αμέσως πριν την έναρξη της εντόπισμένης μετάβασης καλείται το viewWillAppear. Σε αυτή τη στιγμή η οθόνη δεν είναι ακόμα ορατή, αλλά όλα τα subview έχουν σωστά μεγέθη και το περιεχόμενό τους μπορεί να ενημερωθεί με ασφάλεια.
Όταν ο χρήστης πατήσει το κουμπί επιστροφής ή καλέσει προγραμματιστικά το popViewController, το UIKit επιστρέφει στην προηγούμενη οθόνη και καλεί το viewWillAppear σε αυτήν. Αυτό είναι το κύριο σενάριο για το οποίο χρησιμοποιείται το viewWillAppear — ενημέρωση της λίστας μετά την προσθήκη ενός στοιχείου ή συγχρονισμός ρυθμίσεων.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
tableView.reloadData()
updateBadgeCount()
}
Μετά το κλείσιμο ενός τροπικά παρουσιασμένου ελεγκτή, το UIKit καλεί το viewWillAppear στον ελεγκτή που τον παρουσίασε. Αυτό το σενάριο απαιτεί ιδιαίτερη προσοχή αν χρησιμοποιείτε delegates ή closures για να στείλετε δεδομένα πίσω — το viewWillAppear εγγυάται ότι η οθόνη θα ενημερωθεί μετά τη λήψη του αποτελέσματος.
Το TabBarController καλεί το viewWillAppear στον ελεγκτή της επιλεγμένης κάρτέλας κάθε φορά κατά την εναλλαγή. Αν στην κάρτέλα εμφανίζονται δυναμικά δεδομένα — συναλλαγματικές ισοτιμίες, ειδοποιήσεις, κατάσταση χρήστη — το viewWillAppear είναι το ιδανικό σημείο για την ενημέρωσή τους.
viewWillAppear επιλύει αρκετές συγκεκριμένες εργασίες που δεν μπορούν ή δεν είναι βαατικές να εκτελεστούν σε άλλες μεθόδους. Ας εξετάσουμε τις κύριες.
Η πιο συνθισμένη χρήση του viewWillAppear — επαναφόρτωση του UITableView ή UICollectionView σε κάθε εμφάνιση της οθόνης. Αν τα δεδομένα μπορεί να έχουν αλλάξει στην προηγούμενη οθόνη (προσθήκη στοιχείου, αλλαγή κατάστασης), η κλήση reloadData στο viewWillAppear εγγυάται ότι ο χρήστης βλέπει ενημερωμένες πληροφορίες.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
viewModel.synchronize()
tableView.reloadData()
}
Στο viewWillAppear μπορείτε να ρυθμίσετε εύκολα την εμφάνιση του NavigationBar: να το κρύψετε ή να το εμφανίσετε, να αλλάξετε χρώμα, να ορίσετε large title. Αν σε διαφορετικές οθόνες το NavigationBar εμφανίζεται διαφορετικά, το viewWillAppear είναι το σωστό σημείο για αυτές τις αλλαγές, καθώς το viewDidLoad καλείται μόνο μία φορά.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.setNavigationBarHidden(
false, animated: animated
)
navigationController?.navigationBar.prefersLargeTitles = true
tabBarController?.tabBar.isHidden = false
}
Ειδοποιήσεις που έχουν νόημα μόνο όταν η οθόνη είναι ορατή — πληκτρολογίου, ειδοποιήσεις αλλαγής περιεχομένου — εγγράφονται στο viewWillAppear και διαγράφονται στο viewDidDisappear. Αυτό αποτρέπει περιττούς handler-ες όταν η οθόνη δεν είναι ενεργή και προστατεύει από διαρροές μνήμης.
Αν η οθόνη μπορεί να κρυφτεί από την εφαρμογή ή να ελαχιστοποιηθεί, το viewWillAppear είναι ένα βολικό μέρος για επαναφορά της κατάστασης UI: εναλλαγή τμημάτων, επαναφορά θέσης scroll, μηδενισμό προσωρινών αλλαγών. Ο χρήστης λαμβάνει την οθόνη σε προβλέψιμη μορφή σε κάθε εμφάνιση.
Σε οθόνες που εμφανίζουν μετρητές μη αναγνωσμένων μηνυμάτων, αξιολογήσεων ή ειδοποιήσεων, το viewWillAppear είναι το σωστό μέρος για την ενημέρωσή τους. Αν ο χρήστης μπορεί να έχει αλλάξει την ποσότητα σε άλλη οθόνη, εδώ καλείται ο επανυπολογισμός και η ενημέρωση του UITabBarItem.badgeValue ή προσαρμοσμένων δεικτών. Αυτό εγγυάται ότι ο χρήστης βλέπει πάντα ενημερωμένους αριθμούς ανεξάρτητα από το πόσο καιρό βρισκόταν σε άλλες οθόνες.
Ξεχωριστά πρέπει να αναφερθεί η εργασία με collectionView: αν τα δεδομένα στην οθόνη παρουσιάζονται με τη μορφή πλέγματος με κύτταρα που περιέχουν μετρητές ή καταστάσεις, η ενημέρωσή τους στο viewWillAppear πρέπει να είναι επιλεκτική. Αντί για πλήρη reloadData, χρησιμοποιήστε reloadItemsAtIndexPaths για ορατά κύτταρα για να αποφύγετε τρεμόπαιγμα και απώλεια θέσης scroll.
Η κατανόηση της διαφοράς μεταξύ viewWillAppear και viewDidLoad — η βάση της σωστής αρχιτεκτονικής UIViewController. Αυτές οι μέθοδοι έχουν διαφορετική συχνότητα κλήσης, διαφορετικό πλαίσιο και διαφορετικό σκοπό.
viewDidLoad καλείται μία φορά και είναι κατάλληλο για διαμόρφωση που δεν αλλάζει με τον χρόνο: εγγραφή κυττάρων, ορισμός εκπροσώπων, αρχικοποίηση σταθερών. viewWillAppear καλείται σε κάθε εμφάνιση και είναι κατάλληλο για λειτουργίες που πρέπει να επαναλαμβάνονται: ενημέρωση δεδομένων, διαμόρφωση ορατών στοιχείων, συγχρονισμός κατάστασης.
| Χαρακτηριστικό | viewDidLoad | viewWillAppear |
|---|---|---|
| Συχνότητα | Μία φορά | Κάθε φορά κατά την εμφάνιση |
| View ορατό | Όχι | Όχι (σύντομα θα γίνει ορατό) |
| Μεγέθη View | Δεν είναι τελικά | Τελικά |
| Κατάλληλο για | Εφάπαξ διαμόρφωση | Ενημέρωση και συγχρονισμό |
| Εντόπισμός | Δεν εφαρμόζεται | Παράμετρος animated |
Χρυσός κανόνας: αν η λειτουργία πρέπει να εκτελεστεί μόνο μία φορά — βάλτε την στο viewDidLoad. Αν κάθε φορά κατά την επιστροφή στην οθόνη — βάλτε στο viewWillAppear.
Λανθασμένη χρήση του viewWillAppear μπορεί να οδηγήσει σε προβλήματα απόδοσης, υπερβολικές ενημερώσεις και ασυνεπή κατάσταση διαπαφής. Ας εξετάσουμε τα πιο συνθισμένα λάθη.
Πρώτο λάθος — διπλασιασμός λογικής από το viewDidLoad. Αν εγγράφετε κύτταρα πίνακα τόσο στο viewDidLoad όσο και στο viewWillAppear — η εγγραφή θα εκτελείται πολλές φορές, αν και η εφάπαξ διαμόρφωση είναι αρκετή. Μεταφέρετε όλες τις εφάπαξ διαμορφώσεις στο viewDidLoad.
Δεύτερο λάθος — άνευ όρων reloadData σε κάθε εμφάνιση. Αν τα δεδομένα δεν έχουν αλλάξει, η επαναφόρτωση του πίνακα προκαλεί περιττά αιτήματα στην πηγή δεδομένων και επανασχεδίαση κυττάρων, μειώνοντας την απόδοση. Ελέγξτε αν η κατάσταση πραγματικά άλλαξε πριν καλέσετε reloadData.
Τρίτο λάθος — εργασία με αιτήματα δικτύου χωρίς να λάβετε υπόψη ότι η οθόνη μπορεί να κρυφτεί ξανά πριν την ολοκλήρωση του αιτήματος. Αν στο viewWillAppear ξεκινήσετε ένα αίτημα URLSession και ο χρήστης πάει αμέσως σε άλλη οθόνη, το αποτέλεσμα μπορεί να εφαρμοστεί σε ένα ήδη κρυμμένο View. Χρησιμοποιήστε ακυρώσιμες εργασίες ή ελέγξτε isViewLoaded και window πριν από την ενημέρωση.
Τέταρτο λάθος — ξεχάσατε να καλέσετε super. Η μη κλήση super.viewWillAppear μπορεί να διαταράξει τη λειτουργία των γονικών ελεγκτών (UINavigationController, UITabBarController) και να οδηγήσει σε λανθασμένη επεξεργασία χειρονομιών και μεταβάσεων. super πρέπει πάντα να καλείται.
Πέμπτο λάθος — αλλαγή περιορισμών χωρίς κλήση layoutIfNeeded. Αν στο viewWillAppear αλλάζετε προγραμματιστικά περιορισμούς, το UIKit δεν τους εφαρμόζει αμέσως — οι αλλαγές συσσωρεύονται μέχρι την επόμενη διαδρομή layout. Για άμεση εφαρμογή αλλαγών μετά την τροποποίηση περιορισμών, καλέστε view.layoutIfNeeded(). Αυτό είναι ιδιαίτερα σημαντικό κατά τον ορισμό του ύψους στοιχείων που εξαρτώνται από περιεχόμενο.
Έκτο λάθος — προσπάθεια εκτέλεσης εντόπισμού στο viewWillAppear. Όπως αναφέρθηκε παραπάνω, το UIKit επεξεργάζεται ακόμα τον εντόπισμό μετάβασης και ο εντόπισμός σας μπορεί να ανταγωνιστεί με τον εντόπισμό συστήματος. Αν χρειάζεστε ένα στοιχείο να εμφανιστεί με εφέ, χρησιμοποιήστε εντόπισμό εισόδου στο viewDidAppear, και στο viewWillAppear διαμορφώστε μόνο την αρχική κατάσταση: διαφάνεια 0, transform σε κλίμακα 0.8 και ούτω καθεξής.
Έβδομο λάθος — αγνόηση της παραμέτρου animated. Μερικοί προγραμματιστές δεν ελέγχουν την τιμή animated στο viewWillAppear και εκτελούν λειτουργίες που θα έπρεπε να εξαρτώνται από την παρουσία εντόπισμού. Για παράδειγμα, η απόκρυψη NavigationBar με animated = false μπορεί να γίνει χωρίς εντόπισμό, και με animated = true — με εντόπισμό, για να φαίνεται ομαλή η μετάβαση. Πάντα μεταβιβάζετε την παράμετρο animated στις αντίστοιχες μεθόδους UIKit.
Όγδοο λάθος — τροποποίηση UI σε μη ορατή οθόνη. Αν στο viewWillAppear ξεκινήσετε ένα αίτημα δικτύου και το μπλοκ ολοκλήρωσής του ενημερώνει το UI όταν η οθόνη μπορεί να έχει εξαφανιστεί, ο χρήστης θα δει τρεμόπαιγμα ή ασυνεπή κατάσταση. Πάντα ελέγχετε isViewLoaded και window πριν ενημερώσετε το UI σε closures. Αυτή η απλή ενέργεια αποτρέπει crashes και περιττή επανασχεδίαση διαπαφής.
Συχνές ερωτήσεις
viewWillAppear καλείται πριν από την έναρξη του εντόπισμού εμφάνισης, όταν το View δεν είναι ακόμα ορατό. viewDidAppear — μετά το τέλος του εντόπισμού, όταν η οθόνη έχει εμφανιστεί πλήρως και είναι διαθέσιμη για αλληλεπίδραση.
Υπό κανονικές συνθήκες το viewWillAppear καλείται πάντα κατά την εμφάνιση της οθόνης. Εξαίρεση — η βίαιη έξοδος από την εφαρμογή (force quit), όπου το UIKit δεν προλαβαίνει να καλέσει τις μεθόδους Lifecycle.
Ναι, υποχρεωτικά. Το UIKit χρησιμοποιεί αυτή την κλήση για εσωτερικό συντονισμό με UINavigationController και UITabBarController. Χωρίς super μπορεί να χαλάσουν οι χειρονομίες και οι εντόπισμοί μεταβάσεων.
Σε κάθε εναλλαγή κάρτέλας. Το UIKit καλεί το viewWillAppear στον ελεγκτή της επιλεγμένης κάρτέλας μόλις ο χρήστης αγγίξει το αντίστοιχο εικονίδιο στο TabBar.
Χρησιμοποιήστε ιδιότητες του ελεγκτή ή κοινή πηγή δεδομένων. Πριν καλέσετε popViewController, ορίστε τις απαραίτητες τιμές στον προηγούμενο ελεγκτή και στο viewWillAppear του θα είναι ήδη διαθέσιμες.
Περίληψη
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης