Εισαγωγή: Γιατί βασικά δεδομένα και NSFtractedΑποτελέσματαΕλεγκτής ύλη

Στη σύγχρονη ανάπτυξη iOS, η παροχή ενός ρευστού, responsive διεπαφή χρήστη εξαρτάται συχνά από το πόσο αποτελεσματικά χειρίζεται η εφαρμογή σας δεδομένα που αλλάζουν με την πάροδο του χρόνου. Είτε χτίζετε μια κοινωνική τροφοδοσία, έναν διαχειριστή εργασιών, είτε ένα σύστημα απογραφής, τα δεδομένα που εμφανίζονται στους χρήστες είναι σπάνια στατικά. Core Data — Το ώριμο γράφημα αντικειμένων και το πλαίσιο επιμονής της Apple - σε συνδυασμό με [[LFT:0]] (FRC) προσφέρει μια λύση που δοκιμάζεται από μάχη για τη διαχείριση δυναμικών, μεγάλης κλίμακας datasets ενώ διατηρεί το UI σε συγχρονισμό χωρίς χειροκίνητα πάνω.

Αυτό το άρθρο παρέχει έναν σε βάθος, πρακτικό οδηγό για τη χρήση των βασικών δεδομένων με [[LFT:1] οι ειδοποιήσεις είναι το κλειδί. Όταν τα αντικείμενα εισάγονται, ενημερώνονται ή διαγράφονται, το πλαίσιο μεταδίδει αυτές τις αλλαγές, πράγμα που είναι ακριβώς ό, τι [[LFT:2]] μόχλευσης για να κρατήσει το UI σας συνεπή.

Για την επίσημη τεκμηρίωση του προγραμματιστή, ανατρέξτε στο Apple's Core Data Framework Reference.

NSFtraggedResultsΕλεγκτής: Η Γέφυρα Μεταξύ των δεδομένων πυρήνα και το UI σας

είναι ένα αντικείμενο ελεγκτή σχεδιασμένο για την αποτελεσματική διαχείριση των αποτελεσμάτων που επιστρέφονται από ένα αίτημα ανάκτησης δεδομένων πυρήνα, ειδικά όταν τα υποκείμενα δεδομένα αναμένεται να αλλάξουν.

Βασικά χαρακτηριστικά

  • Αυτόματη παρακολούθηση αλλαγών: Το FRC ακούει τις ειδοποιήσεις συμφραζομένων και τις μεταφράζει σε δομημένες εκπρόσωπες κλήσεις (, ], ]).
  • Χτισμένο σε τομή: Προσδιορίζοντας μια , οι ομάδες ελεγκτών φέρνουν αποτελέσματα σε τμήματα, καθιστώντας ασήμαντη την εμφάνιση τομεακών προβολών ή προβολών συλλογής.
  • Βελτιστοποίηση απόδοσης: Το FRC χρησιμοποιεί βλαβές και κάμψη κάτω από την κουκούλα. Φέρνει μόνο δεδομένα όπως χρειάζεται και μπορεί προαιρετικά να χρησιμοποιήσει μια μόνιμη κρύπτη για να αποφύγει την επαναχρησιμοποίηση όταν το υπό διαχείριση πλαίσιο αντικείμενο αποθηκεύεται.

Εκπρόσωπες μέθοδοι λεπτομέρειας

Για να επωφεληθείτε πλήρως από τον ελεγκτή, πρέπει να εφαρμόσετε το ]. Το πιο συνηθισμένο μοτίβο είναι να χρησιμοποιήσετε αυτές τις κλήσεις μέσα σε ή να αναθέσετε την ενημέρωση παρτίδας του UI. Για παράδειγμα:

func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
 tableView.beginUpdates()
}

func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>,
 didChange anObject: Any,
 at indexPath: IndexPath?,
 for type: NSFetchedResultsChangeType,
 newIndexPath: IndexPath?) {
 switch type {
 case .insert:
 tableView.insertRows(at: [newIndexPath!], with: .fade)
 case .delete:
 tableView.deleteRows(at: [indexPath!], with: .fade)
 case .update:
 tableView.reloadRows(at: [indexPath!], with: .fade)
 case .move:
 tableView.moveRow(at: indexPath!, to: newIndexPath!)
 @unknown default:
 tableView.reloadData()
 }
}

func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
 tableView.endUpdates()
}

Αυτό το μοτίβο εξασφαλίζει ότι η προβολή πίνακα ενεργοποιεί αλλαγές σε συγχρονισμό με τα υποκείμενα δεδομένα, εμποδίζοντας το flicker ή την ασυνέπεια.

Εφαρμογή βήμα προς βήμα

Παρακάτω είναι ένα πλήρες, έτοιμο για παραγωγή παράδειγμα χρησιμοποιώντας το Swift 5, με στόχο το iOS 15+. Θα υποθέσουμε μια απλή οντότητα που ονομάζεται με χαρακτηριστικά (Στρινγκ) και (Μπουλ), και ένα (Ημερομηνία).

1. ⁇ της βάσης δεδομένων

Στις ή σε ένα αφιερωμένο (συχνές σε εφαρμογές SwiftUI), δημιουργήστε το επίμονο δοχείο:

class PersistenceController {
 static let shared = PersistenceController()
 let container: NSPersistentContainer

 init() {
 container = NSPersistentContainer(name: "YourModelName")
 container.loadPersistentStores { storeDescription, error in
 if let error = error as NSError? {
 fatalError("Unresolved error \(error), \(error.userInfo)")
 }
 }
 container.viewContext.automaticallyMergesChangesFromParent = true
 }
}

2. Δημιουργήστε την υποκατηγορία NSManagedObject

Χρησιμοποιήστε τον επεξεργαστή του μοντέλου δεδομένων του Xcode για να δημιουργήσετε τα αρχεία κλάσης, ή να τα δημιουργήσετε χειροκίνητα. Βεβαιωθείτε ότι η οντότητα σας χρησιμοποιεί τη σωστή ρύθμιση ενότητας κλάσης.

3. ⁇ της αίτησης και FRC ανάκτησης

Στο χειριστήριο προβολής σας, ρυθμίστε το αίτημα ανάκτησης και αρχικοποιήστε το ληφθέν ελεγκτή αποτελεσμάτων. Είναι καλύτερο να το εκτελέσετε αυτό σε [[LFT:19]]] ή ένα μοντέλο προβολής init.

lazy var fetchedResultsController: NSFetchedResultsController<Task> = {
 let fetchRequest: NSFetchRequest<Task> = Task.fetchRequest()
 let sortDescriptor = NSSortDescriptor(key: "dueDate", ascending: true)
 fetchRequest.sortDescriptors = [sortDescriptor]
 // Optional: limit results with batch size for large datasets
 fetchRequest.fetchBatchSize = 20

 let controller = NSFetchedResultsController(
 fetchRequest: fetchRequest,
 managedObjectContext: PersistenceController.shared.container.viewContext,
 sectionNameKeyPath: "completionStatus", // e.g., a transient attribute or a computed property
 cacheName: nil
 )
 controller.delegate = self
 try? controller.performFetch()
 return controller
}()

4. Οδηγήστε την προβολή πίνακα με το FRC

Οι μέθοδοι σας γίνονται ασήμαντες:

func numberOfSections(in tableView: UITableView) -> Int {
 fetchedResultsController.sections?.count ?? 0
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
 let sectionInfo = fetchedResultsController.sections![section]
 return sectionInfo.numberOfObjects
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
 let cell = tableView.dequeueReusableCell(withIdentifier: "TaskCell", for: indexPath)
 let task = fetchedResultsController.object(at: indexPath)
 configure(cell, with: task)
 return cell
}

Προσέξτε ότι ποτέ δεν καλέστε χειροκίνητα — οι μέθοδοι ανάθεσης χειρίζονται κάθε εισαγωγή, διαγραφή, και ενημέρωση.

Προηγμένη Χρήση και Βέλτιστες Πρακτικές

Ασφάλεια νημάτων

Τα βασικά δεδομένα δεν είναι ασφαλή. Πάντα χρησιμοποιήστε το [[LFT:24]] (που τρέχει στην κύρια ουρά) για όλες τις αιτήσεις παραλαβής που σχετίζονται με το UI και τα FRCs. Για εργασίες φόντου, δημιουργήστε ένα πλαίσιο ιδιωτικής ουράς και συγχωνεύστε αλλαγές στο πλαίσιο της προβολής. Αποφύγετε τη χρήση του ίδιου FRC σε πολλαπλές ουρές.

Κοίλωμα

Η παράμετρος μπορεί να βελτιώσει την απόδοση εκκίνησης επιμένοντας στο τμήμα και τις πληροφορίες αντικειμένου. Ωστόσο, εάν αλλάξει το αίτημά σας ή το μοντέλο δεδομένων, πρέπει να διαγράψετε την κρύπτη () για να αποφύγετε τη διαφθορά.

Χειρισμός μεγάλων συνόλων δεδομένων

Χρησιμοποιήστε για να περιορίσετε τον αριθμό των αντικειμένων που έχουν ληφθεί στη μνήμη. Επίσης, εξετάστε τη ρύθμιση [[LFT:28]] μόνο αν χρειάζεστε άμεση πρόσβαση σε κάθε ακίνητο. Για δεδομένα έντασης σχέσης, προ-fetching με [[LFT:29]] μπορεί να αποτρέψει επαναλαμβανόμενα ελαττώματα.

Ολοκλήρωση με το SwiftUI

Ενώ είναι UIKit ⁇ κεντρικό, μπορείτε ακόμα να το χρησιμοποιήσετε στο SwiftUI περιτυλίσσοντάς το σε [] ή χρησιμοποιώντας το νεότερο περιτύλιγμα ιδιοκτησίας (το οποίο εσωτερικά χρησιμοποιεί παρόμοιο μηχανισμό).Για σύνθετα δυναμικά δεδομένα στο SwiftUI, είναι συνήθως επαρκές, αλλά το FRC σας δίνει λεπτό-εμπλουτισμένο έλεγχο πάνω σε κινούμενα σχέδια και παρτίδες.

Συχνές Παγίδες και Πώς να τις Αποφύγετε

  • Ξεχνώντας : Ο ελεγκτής δεν θα εκτελέσει την ανάκτηση μέχρι να καλέσετε αυτή τη μέθοδο. Κάντε το μία φορά, συνήθως αμέσως μετά την αρχικοποίηση.
  • Μη οριζόμενος ο αντιπρόσωπος: Χωρίς εκπρόσωπο, οι αλλαγές δεν θα διαδοθούν στην οπτική του τραπεζιού. Πάντα καλεί .
  • Εσφαλμένες περιγραφείς ταξινόμησης: Αν η διαδρομή κλειδί ονόματος τμήματος σας δεν ταιριάζει με την περιγραφή πρώτης ταξινόμησης, οι ενότητες μπορεί να εμφανίζονται εκτός σειράς. Βεβαιωθείτε ότι το χαρακτηριστικό που χρησιμοποιείται στο εμφανίζεται στους περιγραφείς ταξινόμησης.
  • Χρησιμοποιώντας παράλληλα με το FRC: Καλώντας ενώ το FRC κινώντας αλλαγές μπορεί να προκαλέσει καταρρεύσεις. Αφήστε τον αντιπρόσωπο μεθόδους χειριστεί όλες τις ενημερώσεις UI.
  • Αγνοώντας το πλαίσιο βασικών δεδομένων αποθηκεύουν τις αποτυχίες: Αν αποθηκεύσετε το πλαίσιο και ένα σφάλμα, το FRC μπορεί να μην ειδοποιηθεί. Πάντα να χειρίζεστε σφάλματα και να εξετάζετε τη χρήση σε παρασκηνιακά πλαίσια.

Επιδόσεις

είναι ήδη αποτελεσματική, αλλά εδώ είναι πρόσθετες βελτιστοποιήσεις:

  • Χρησιμοποιήστε τα προκαθορισμένα με σύνεση: Ένα σύνθετο προκαθορισμένο μπορεί να επιβραδύνει την αρχική λήψη. Χρησιμοποιήστε τα ευρετηριωμένα χαρακτηριστικά όπου είναι δυνατόν.
  • Όριο που λαμβάνονται ιδιότητες: Αν χρειάζεστε μόνο ορισμένα χαρακτηριστικά, ρυθμίστε στην αίτηση παραλαβής.
  • Ενημέρωση παρτίδας: Όταν κάνετε πολλές αλλαγές, τυλίξτε τις σε ένα μπλοκ για να μειώσετε τον αριθμό των εκπρόσωπων κλήσεων.
  • Αποφύγετε περιττό σφάλμα: Αν γνωρίζετε ότι θα έχετε πρόσβαση σε όλα τα αντικείμενα σε ένα σύνολο αποτελεσμάτων, χρησιμοποιήστε για να τα προ-φύγετε, αλλά να είστε προσεκτικοί με τη μνήμη.

Για μια βαθύτερη κατάδυση στην απόδοση των βασικών δεδομένων, δείτε Οδηγός Απόδοσης βασικών δεδομένων της Apple.

⁇ αλιστικά ⁇ Παγκόσμια Παραδείγματα

Παράδειγμα 1: Εφαρμογή συνομιλίας

Μια εφαρμογή μηνυμάτων εμφανίζει μια λίστα συνομιλιών ταξινομημένων με το πιο πρόσφατο μήνυμα. Νέα εισερχόμενα μηνύματα θα πρέπει να εμφανίζονται αμέσως. Χρησιμοποιώντας μια FRC, η προβολή επαφών μπορεί να εγγραφεί σε αλλαγές μόνο για τις τρέχουσες οντότητες συνομιλίας του χρήστη.

Παράδειγμα 2: Διαχείριση Αποθεμάτων

Όταν τα επίπεδα των αποθεμάτων αλλάζουν από ένα συγχρονισμό φόντου, το FRC ενημερώνει αυτόματα το UI. Ρυθμίζοντας [[LFT:44]] σε 50, η προβολή παραμένει ανταποκρίσιμη ακόμα και με χιλιάδες αντικείμενα.

Παράδειγμα 3: Λίστα ⁇ Να κάνει με τις κατηγορίες

Το κλασικό παράδειγμα: εργασίες που ομαδοποιούνται σε ⁇ Υπερβολική ⁇ ⁇ Σήμερα ⁇ και ⁇ Ανερχόμενη ⁇ Το [[LFT:45]] μπορεί να είναι ένα παροδικό παράγωγο χαρακτηριστικό που υπολογίζεται από [[LFT:46]]] και τρέχουσα ημερομηνία. Βεβαιωθείτε ότι η ίδια παράγωγη τιμή χρησιμοποιείται στον περιγραφέα ταξινόμησης για την αποφυγή αναντιστοιχιών.

Συμπέρασμα

Η εξουσιοδότηση του συνδυασμού των δεδομένων πυρήνα και [[LFT:47]] αποτελεί ακρογωνιαίο λίθο της οικοδόμησης στιβαρών, δυναμικών εφαρμογών iOS. Με την εκφόρτωση της βαριάς ανύψωσης της παρακολούθησης αλλαγών και του συγχρονισμού UI στα πλαίσια της Apple, μπορείτε να επικεντρωθείτε στη δημιουργία μιας μεγάλης εμπειρίας χρήστη και όχι στη συγγραφή δεδομένων λεβήτων ⁇ κώδικα διαχείρισης.

Είτε διατηρείτε μια κληρονομιά UIKit εφαρμογή ή υιοθετώντας SwiftUI με [[LFT:48]], οι αρχές παραμένουν οι ίδιες: κατανοήστε το γράφημά σας αντικείμενο, ρυθμίστε την ανάκτηση αιτήσεων προσεκτικά, και αφήστε τον επιλεγμένο ελεγκτή αποτελεσμάτων να κάνει ό, τι κάνει καλύτερα. Με τις πρακτικές που περιγράφονται σε αυτό το άρθρο — συμπεριλαμβανομένης της caching, της ασφάλειας νημάτων, και του συντονισμού επιδόσεων ⁇ θα είστε καλά εξοπλισμένοι για να χειριστεί οποιοδήποτε σύνολο δεδομένων που εξελίσσεται με την πάροδο του χρόνου.

Για περαιτέρω εξερεύνηση, ελέγξτε το Core Data tutorial του Ρέι Βέντερλιχ και το άρθρο NSHipster για τα NSFtractedResultsControler].