הקדמה: למה מידע Core ו- NSFetchedResultsController Matter

בפיתוח iOS מודרני, מתן ממשק משתמש נוזלי, תגובתי לעתים קרובות תלוי כמה יעיל האפליקציה שלך מטפל נתונים שינויים לאורך זמן.אם אתה בונה מזון חברתי, מנהל משימה, או מערכת מלאי, הנתונים המוצגים למשתמשים הוא לעתים רחוקות סטטי. - גרף האובייקטים הבוגר של אפל ומסגרת ההתעקשות - יחד עם FLT:0 (FRC) מציע פתרון מאבק עבור נתונים בקנה מידה גדול, ניהול נתונים בקנה מידה גדול של UI ללא סנכרון נתונים ללא סנכרון ידני.

מאמר זה מספק מדריך מעמיק ומעשי לשימוש בנתונים Core עם הודעות FLT:1 הוא מפתח.כאשר אובייקטים מוכנסים, מעודכנים, או נמחקים, ההקשר משדר שינויים אלה, וזה בדיוק מה ש-FLT:2 ממינוף כדי לשמור על עקביות UI שלך.

לתיעוד מפתח רשמי, התייחס ל-FLT:0 ,(ה- Core Data Framework Referenceing) של אפל 1.

NSFetchedRescontroller: הגשר בין נתוני הליבה לבין UI שלך

(FLT:3) הוא אובייקט בקר שנועד לנהל ביעילות את התוצאות חזרו מבקשת העברת נתונים Core, במיוחד כאשר הנתונים הבסיסיים צפויים להשתנות.הוא מפקח על ההקשר האובייקטיבי הרלוונטי ודיווח אוטומטית שינויים באמצעות פרוטוקול הציר שלו.

תכונות מפתח

  • (ב) ויקרא ה': ויקרא י"א): "ה'ו' יקשיב ל''' (ב') ל'''' (ב')' (ב')' (ב')''' (ב')'', ו'''''''''''''' (')')'''''''')''''
  • (ב) בפרשת [[המאה ה-1]], [[1924]], [[1924]]]], [[1924]]]], [[1924]]]], [[1924]]]]]], [[1924]]]]]], [[1924]]]]]], [[1924]]]]]]]], [[1924]]]]]]]], [[1924]]]]]]
  • (FLT:0) אופטימיזציה לפורמציה: 1FLT:1 ה- FRC משתמש בהאשמה ובסגידה מתחת למכסה.זה רק מביא נתונים הדרושים ויכול להשתמש במזיקים מתמידים כדי להימנע מפגיעה חוזרת כאשר ההקשר האובייקט מנוהל נשמר.

שיטות של Delegate בפירוט

כדי להפיק תועלת מלאה מהבקר, עליך ליישם את ה-FLT:8 דפוס הנפוץ ביותר הוא להשתמש בקריאות אלה בתוך FLT:9 או FLT:10 נציג כדי לקבץ את 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+.We'll take a Simpleישות הנקראת FLT:12 עם תכונות FLT:13 (String) ו-FLT:14 (Bool), ו-FLT:15 (Date).

המונחים: the right data Stack

ב[[1824]], [[1924]]]], [[1924]]]], [[1924]]]], [[1924]]]]]], [[1924]]]]]], [[1924]]]]]]]]

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 Subclass

השתמש עורך מודל הנתונים של Xcode כדי ליצור את הקבצים בכיתה, או ליצור אותם באופן ידני.לוודא שהישות שלך משתמשת הגדרת מודול הכיתה הנכונה.

3.הגדירו את הבקשה Fetch ו-FRC

בבקר התצוגה שלך, להגדיר את הבקשה להביא ולהחילה את בקר התוצאות הנלהבות.זה הכי טוב לבצע את זה בFLT:19 או מודל תצוגה של מודל.

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

שיטות ה-FLT:21 שלך הופכות לטריוויה:

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
}

שימו לב שמעולם לא התקשרו באופן ידני לשיטות הציר מטפלות בכל שילוב, מחיקה ועדכון.

שיטות מתקדמות ותרגולים טובים ביותר

המונחים בטיחות

ההקשרים של הנתונים המרכזיים אינם בטוחים חוטים.תמיד להשתמש ב-FLT:24 (אשר פועל על התור הראשי) עבור כל בקשות ה- FRC הקשורות ל- UI. עבור עבודות רקע, ליצור קו פרטי ומיזוג שינויים בהקשר התצוגה.

Caching

פרמטר הפרמטר יכול לשפר את ביצועי ההשקה על ידי רצף ואובייקט מידע, אם בקשת ההחזר או מודל הנתונים שלך משתנה, עליך למחוק את ה- cache (FLT:26) כדי למנוע שחיתות.

עקבו אחרי Large Datasets

השתמש ב-FLT:27 כדי להגביל את מספר האובייקטים שהובאו לזיכרון, יש לשקול הגדרה (FLT:28 רק אם אתה צריך גישה מיידית לכל נכס.

אינטגרציה עם SwiftUI

בעוד ש-FLT:30 הוא UIKit-centric, אתה עדיין יכול להשתמש בו ב- SwiftUI על ידי עוטפת אותו ב-FLT:31 או באמצעות ה-FLT:32 רכוש עטיפה (שבתוך כך משתמש מנגנון דומה) עבור נתונים דינמיים מורכבים ב- SwiftUI,FLT:33 הוא בדרך כלל מספיק, אבל ה-FRC נותן לך שליטה על אנימציה ו- זחלת.

מלכודות נפוצות וכיצד להימנע מהם

  • (ב) [ה]הבקר לא יבצע את הלהבה עד שתקראו לה שיטה זו, בדרך כלל מיד לאחר ההשלמה.
  • (ב) לא יכניסו את ה' אלקים' (ב"ג) ל[[המאה ה-20]], ולא יקומו שינויים ב[[1924]], ולא יועדו ל[[1924]].
  • (ב) אם שם הסעיף שלך אינו תואם את המפיץ הראשון, חלקים עשויים להופיע מתוך סדר.
  • (ב) [ה]ב[[1924]]]], [[1924]]]], [[1924]]]]]], [[1924]]]]]], [[1924]]]]]], [[1924]]]]]], [[1924]]]]]], [[1924]]]]]]]], [[1924]]]]]]]]]], [[1924]]]]]], [[1924]]]]
  • (ב) אם אתה שומר על הקשר ושגיאה מתרחשת, ייתכן ש-FRC תמיד מטפל שגיאות ויבחן באמצעות שימוש ב-FLT:39 בהקשרים של רקע.

שיקולים

(FLT:40) הוא כבר יעיל, אבל הנה עוד אופטימיזציה:

  • (ב) ,0) ,Use predicates בחוכמה: FLT:1 מורכב predicate יכול להאט את הסימון הראשוני של שימוש בתכונות אינדקס במידת האפשר.
  • (ב) אם אתה צריך רק תכונות מסוימות, להגדיר את ה- 7.
  • (ב) ,0) העדכונים: 1 כאשר הם עושים שינויים רבים, עוטפים אותם בבלוק (FLT:42) כדי להפחית את מספר הקריאות של הנציגים.
  • (ב) אם אתה יודע שאתה ניגש לכל האובייקטים בתוצאה, השתמש ב-FLT:43 כדי להדוף אותם, אך להיות זהיר עם זיכרון.

לצליל עמוק יותר לתוך ביצועי נתונים Core, ראה:0) של אפל ביצועי נתונים Core של אפל (Hal Data Performance GuideFLT:1).

דוגמאות אמיתיות בעולם

דוגמא 1: יישום

אפליקציית הודעות מציגה רשימה של שיחות המאופיינות על ידי הודעה עדכנית ביותר.הודעות חדשות צריכות להופיע מיד.שימוש ב-FRC, נקודת המגע יכולה להירשם לשינויים רק עבור ישויות השיחה של המשתמש הנוכחי.חלקו על ידי קבוצות תאריך לתוך "היום", "אתמול", וכו '.

דוגמה 2: ניהול מלאי

אפליקציית מסחר אלקטרוני מציגה מוצרים בקטגוריות.כאשר רמות המניות משתנות מסנכרן רקע, ה-FRC מעדכן באופן אוטומטי את UI. על ידי הגדרת ההרחבה FLT:44 עד 50, התצוגה נותרה תגובה גם עם אלפי פריטים.

דוגמה: רשימת עריכת קטגוריות

הדוגמה הקלאסית: משימות שנכללו ב"הרחבה", "היום", ו"התקרבות" (FLT:45) יכולות להיות תכונה נגזרת מ-FLT:46 ותאריך נוכחי.

מסקנה

שילוב של נתוני Core ו-FLT:47 הוא אבן הפינה של בניית יישומים חזקים, דינמי iOS.על ידי הסרת המריבה הכבדה של מעקב שינוי והסנכרון UI למסגרות של אפל, אתה יכול להתמקד ביצירת חוויית משתמש מעולה במקום לכתוב קוד נתונים של רתטרנדרלה.

בין אם אתה שומר על אפליקציה מורשת UIKit או אימוץ SwiftUI עם FPLT:48, העקרונות נשארים זהים: להבין את הגרף האובייקט שלך, להגדיר בקשות בקפידה, ולתת לבקר התוצאות הנלהב לעשות מה שהוא עושה הכי טוב.עם הפרקטיקה המתוארת במאמר זה - כולל כיס, בטיחות וביצועים - אתה תהיה מצויד היטב כדי לטפל בכל סוג של נתונים מתפתח לאורך זמן.

(ב) ב[[1924]], [[1924]]]]]], [[1924]]]]]] ו[[1924]]]], [[1924]]]]]], [[1924]]]]]]]]]] ו[[1924]]]]]]