Алексей Додонов "Опыт использования Core Data в Яндекс.Почте"

4,963 views

Published on

Core Data – простой, понятный и удобный способ доступа к данным. Несмотря на обещанную простоту Core Data, на практике в нем есть немало подводных камней.

Алексей Додонов рассказал о некоторых из них, а также о том, как работать с Core Data в многопоточном приложении.

0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
4,963
On SlideShare
0
From Embeds
0
Number of Embeds
2,343
Actions
Shares
0
Downloads
17
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

Алексей Додонов "Опыт использования Core Data в Яндекс.Почте"

  1. 1. Core DataПлюсы, минусы и подводные камни 1
  2. 2. Хранение данных• SQLite• Core Data• Archives and Serializations• User Defaults System 2
  3. 3. 3
  4. 4. Core Data или SQLite? 3
  5. 5. myFolder newMessage Core Data 4
  6. 6. myFolder newMessage .message .folder Core Data 4
  7. 7. myFolder newMessage .message .foldermyFolder.message = newMessage; Core Data 4
  8. 8. myFolder newMessage .message .foldermyFolder.message = newMessage;newMessage.folder = myFolder; Core Data 4
  9. 9. .folder = myFolder.messagesmessage1message2 .folder = myFolder Core Data 5
  10. 10. .folder = myFolder.messagesmessage1message2 .folder = myFolder .folder Core Data 5
  11. 11. .folder = myFolder.messagesmessage1message2 .folder = myFolder .folder = myFolder Core Data 5
  12. 12. .folder = myFolder.messagesmessage1message2 .folder = myFoldermessage3 .folder = myFolder Core Data 5
  13. 13. 1 1 .label = {label1}.messages = {m1} 2 .label = {label1} 2 3.messages = {m2, m3} .label = {label2} Core Data 6
  14. 14. 1 1 .label = {label1}.messages = {m1, m2} 2 .label = {label1, label2} 2 3.messages = {m2, m3} .label = {label2} Core Data 6
  15. 15. Delete Rules• Nullify• Cascade• Deny 7
  16. 16. nullify .folder.message Delete Rules 8
  17. 17. nullify.message Delete Rules 8
  18. 18. .message = nil Delete Rules 8
  19. 19. 1 1 .label = {label1}.messages = {m1, m2} 2 2 .label = {label1, label2} 3.messages = {m2, m3} .label = {label2} Delete Rules 9
  20. 20. 1 1 .label = {label1}.messages = {m1, m2} 2 3.messages = {m2, m3} .label = {label2} Delete Rules 9
  21. 21. 1 1 .label = {label1}.messages = {m1} 2 3.messages = {m3} .label = {label2} Delete Rules 9
  22. 22. cascadeDelete Rules 10
  23. 23. cascadeDelete Rules 10
  24. 24. Delete Rules 10
  25. 25. denyDelete Rules 11
  26. 26. denyDelete Rules 11
  27. 27. denyDelete Rules 11
  28. 28. NSManagedObjectMemory Management 12
  29. 29. Fault FaultMemory Management 13
  30. 30. Folder FaultFault FaultMemory Management 14
  31. 31. Folder FaultFault Message Fault FaultMemory Management 15
  32. 32. Folder FolderFault Message Message Message Attach AttachMemory Management 16
  33. 33. Fault FaultFault Fault Fault Fault Fault FaultMemory Management 17
  34. 34. Object Oriented 18
  35. 35. Model Versioning 19
  36. 36. NSFetchedResultsController- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return [[self.fetchedResultsController sections] count];}- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section { id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section]; return [sectionInfo numberOfObjects];}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = <#Get the cell#>; NSManagedObject *managedObject = [self.fetchedResultsController objectAtIndexPath:indexPath]; return cell;}- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {  id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section]; return [sectionInfo name];}- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView { return [self.fetchedResultsController sectionIndexTitles];}- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index { return [self.fetchedResultsController sectionForSectionIndexTitle:title atIndex:index];} Interface 20
  37. 37. Подводные камни 21
  38. 38. NSSet *messages Ordered Collections 22
  39. 39. 1NSSet *messages 2 3 Ordered Collections 22
  40. 40. 1NSSet *messages 2 3NSSet *messages Ordered Collections 22
  41. 41. NSSet *messages 1 2NSSet *messages Ordered Collections 22
  42. 42. 11 22 3Ordered Collections 23
  43. 43. 11 folder1 1 message1 folder1 2 message2 2 folder1 3 message3 folder2 1 message22 folder2 2 message3 3Ordered Collections 23
  44. 44. DELETE FROM links WHERE folder = ‘folder1’ 11 folder1 1 message1 folder1 2 message2 2 folder1 3 message3 folder2 1 message22 folder2 2 message3 3Ordered Collections 23
  45. 45. 11 folder1 1 message1 folder1 2 message2 2 folder1 3 message3 folder2 1 message22 folder2 2 message3 3Ordered Collections 23
  46. 46. 11 2 folder2 1 message22 folder2 2 message3 3Ordered Collections 23
  47. 47. 24
  48. 48. UPDATE message SET unread = 0 WHERE folder = ‘folder1’ 24
  49. 49. 24
  50. 50. 24
  51. 51. 25
  52. 52. 25
  53. 53. 26
  54. 54. .folder = myFolder; 26
  55. 55. myFolder.folder = myFolder; 26
  56. 56. Fault.folder = myFolder; 26
  57. 57. 26
  58. 58. 27
  59. 59. NSManagedObjectID.folder = [myFolder objectID]; 27
  60. 60. 28
  61. 61. NSManagedObjectContext *moc = [self managedObjectContext]; 28
  62. 62. NSManagedObjectContext *moc = [self managedObjectContext];NSError *error = nil;MailFolder *folder = (MailFolder *)[moc existingObjectWithID:self.folder error:&error]; 28
  63. 63. NSManagedObjectContext *moc = [self managedObjectContext];NSError *error = nil;MailFolder *folder = (MailFolder *)[moc existingObjectWithID:self.folder error:&error];if (error != nil) { // TODO: handle error!} 28
  64. 64. NSManagedObjectContext *moc = [self managedObjectContext];NSError *error = nil;MailFolder *folder = (MailFolder *)[moc existingObjectWithID:self.folder error:&error];if (error != nil) { // TODO: handle error!}if (folder != nil) { self.navigationItem.title = folder.name;} 28
  65. 65. Core Data is notthread-safe 29
  66. 66. 30
  67. 67. Main ThreadBackground Thread 30
  68. 68. Main ThreadBackground Thread 30
  69. 69. Main ThreadBackground Thread 30
  70. 70. Main ThreadFetch or SaveBackground Thread 31
  71. 71. FetchMain ThreadBackground Thread 31
  72. 72. Main ThreadBackground ThreadFetch 31
  73. 73. Main ThreadBackground ThreadFetch NSManagedObjectID NSManagedObjectID NSManagedObjectID 31
  74. 74. NSManagedObjectID NSManagedObjectID NSManagedObjectIDMain ThreadBackground ThreadFetch 31
  75. 75. NSManagedObjectID NSManagedObjectIDMain ThreadBackground ThreadFetch 31
  76. 76. NSManagedObjectIDMain ThreadBackground ThreadFetch 31
  77. 77. Main ThreadBackground ThreadFetch 31
  78. 78. Main ThreadBackground Thread 32
  79. 79. Main Thread ManagerBackground Thread 32
  80. 80. Main Thread[ Manager managedObjectContext] Background Thread 32
  81. 81. moc Main Thread[ Manager managedObjectContext] Background Thread moc 32
  82. 82. mocMain Thread ManagerBackground Thread moc 32
  83. 83. mocMain Thread ManagerBackground Thread moc 32
  84. 84. mocMain Thread ManagerBackground Thread moc 32
  85. 85. moc Main Thread[ Manager saveContext] Background Thread moc 32
  86. 86. moc Main Thread[ Manager saveContext] Background Thread [moc save] moc 32
  87. 87. moc Main Thread[ Manager didSaveManagedObjectContextNotification:notification] Background Thread moc 32
  88. 88. moc [moc mergeChangesFromContextDidSaveNotification:notification] Main Thread[ Manager didSaveManagedObjectContextNotification:notification] Background Thread moc 32
  89. 89. moc [moc mergeChangesFromContextDidSaveNotification:notification] Main Thread[ Manager didSaveManagedObjectContextNotification:notification] Background Thread moc 32
  90. 90. NSFetchedResultsController 33
  91. 91. NSFetchedResultsController • Анимация при изменении списка объектов 33
  92. 92. NSFetchedResultsController • Анимация при изменении списка объектов • Данные изменяются прямо под руками 33
  93. 93. 34
  94. 94. Tips & Tricks 35
  95. 95. Сохраняйтесь чаще 36
  96. 96. Сохраняйтесь чаще{ < блок изменений >; [context save];}{ < блок изменений >; [context save];} 36
  97. 97. Multiple Errors 37
  98. 98. Multiple ErrorsNSMutableString *errorMessage = [NSMutableString stringWithCapacity:0];NSArray* detailedErrors = [[error userInfo] objectForKey:NSDetailedErrorsKey];if ([detailedErrors count] > 0) { for (NSError* detailedError in detailedErrors) { [errorMessage appendFormat:@" DetailedError: %@", [detailedError userInfo]]; [errorMessage appendString:@"n"]; }}else { [errorMessage appendFormat:@" %@", [error userInfo]];}NSLog(errorMessage); 37
  99. 99. NSFetchRequest 38
  100. 100. NSFetchRequest[fetchRequest setFetchBatchSize:25]; 38
  101. 101. NSFetchRequest[fetchRequest setFetchBatchSize:25]; Proxy Array 38
  102. 102. NSFetchRequest[fetchRequest setFetchBatchSize:25]; 25 Proxy Array 38
  103. 103. NSFetchRequest[fetchRequest setFetchBatchSize:25]; 25 25 25 Proxy Array 38
  104. 104. NSFetchRequest[fetchRequest setFetchBatchSize:25]; 25 25 25 Proxy Array[fetchRequest setReturnsObjectsAsFaults:NO]; 38
  105. 105. NSFetchRequest[fetchRequest setFetchBatchSize:25]; 25 25 25 Proxy Array[fetchRequest setReturnsObjectsAsFaults:NO];[fetchRequest setRelationshipKeyPathsForPrefetching:keyPaths]; 38
  106. 106. NSFetchRequest[fetchRequest setResultType:NSManagedObjectIDResultType]; 38
  107. 107. Порядок аргументов 39
  108. 108. Порядок аргументов[NSPredicate predicateWithFormat:@"(subj like ‘mblt12’) AND (unread = 0)"]; 39
  109. 109. Порядок аргументов[NSPredicate predicateWithFormat:@"(subj like ‘mblt12’) AND (unread = 0)"];[NSPredicate predicateWithFormat:@"(unread = 0) AND (subj like ‘mblt12’)"]; 39
  110. 110. SQLite Engine 40
  111. 111. Core Data is an object-graph management and persistence framework. © AppleCore Data is not a database abstraction layer. It is an object hierarchy that happens to persist to disk. © Marcus S. Zarra 41
  112. 112. Спасибо! Алексей Додонов dodonov@yandex-team.ru 42

×