Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
ICYMI: Core Data at CMD+R 2014
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Kyle Fuller
October 22, 2014
Technology
350
3
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
ICYMI: Core Data at CMD+R 2014
https://github.com/QueryKit
Kyle Fuller
October 22, 2014
More Decks by Kyle Fuller
See All by Kyle Fuller
Design APIs and deliver what you promised
kylef
0
150
Preparing for the future of API Description Languages
kylef
0
130
Resilient API Design
kylef
1
360
Building a Swift Web API and Application Together
kylef
2
2.1k
Testing without Xcode - CMD+U 2016
kylef
0
300
End-to-end: Building a Web Service in Swift (MCE 2016)
kylef
2
510
Designing APIs for Humans - Write the Docs 2016
kylef
0
360
Embracing Change - MBLTDev 2015
kylef
3
700
Practical Declarative Programming (360 iDev 2015)
kylef
3
560
Other Decks in Technology
See All in Technology
現場のトークンマネジメント
dak2
1
190
Comment regagner la souveraineté de vos données tout en étant payé grâce à Nostr !
rlifchitz
0
200
クレデンシャル流出 ― 攻撃 3 時間 vs 復旧 10 時間。この非対称性にどう備えるか
kazzpapa3
3
570
GitHub Copilot 最新アップデート – 「一歩先」の実践活用術
moulongzhang
5
1.9k
ロボティクスの技術 / Robotics Technology
ks91
PRO
0
130
MUSUBI 田中裕一『AIと共に行う「しごとのリデザイン」- スモールバックオフィス編』AI Ops Lab #4
musubi
0
320
4人目のSREはAgent
tanimuyk
0
180
LayerX コーポレートエンジニアリング室におけるサプライチェーンセキュリティへの取り組み / Supply Chain Security at LayerX Corporate Engineering
yuyatakeyama
3
840
2026-06-24_人とAIの責務分離に基づく開発プロセスの提案.pdf
takahiromatsui
0
180
いまさら聞けない「仕様駆動開発入門」 〜AI活用時代の開発プロセスを考える〜
findy_eventslides
2
210
事業会社における 機械学習・推薦システム技術の活用事例と必要な能力 / ml-recsys-in-layerx-wantedly-2026
yuya4
0
160
元銀行員がAIだけでアプリを量産!「バイブコーディング実演セミナー 」
tatsuya1970
0
110
Featured
See All Featured
Abbi's Birthday
coloredviolet
3
8.2k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
32
2.9k
A Modern Web Designer's Workflow
chriscoyier
698
190k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
12
1.2k
Scaling GitHub
holman
464
140k
Jamie Indigo - Trashchat’s Guide to Black Boxes: Technical SEO Tactics for LLMs
techseoconnect
PRO
0
190
Faster Mobile Websites
deanohume
310
32k
Designing Powerful Visuals for Engaging Learning
tmiket
1
430
New Earth Scene 8
popppiees
3
2.4k
Bioeconomy Workshop: Dr. Julius Ecuru, Opportunities for a Bioeconomy in West Africa
akademiya2063
PRO
1
150
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
32
3.5k
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
62
44k
Transcript
ICYMI:&Core&Data !@kylefuller
!@kylefuller
None
None
CoreData
What%is%Core%Data?
Framework)for)persistence)and) object)graph)management
Database
SQL$Wrapper$or$ORM
None
Change'No*fica*on
Key$Value$Observing
RACObserve(person, "name").subscribeNext { name in println("Person's name did change to
\(name).") }
NSManagedObjectContextObjectsDidChangeNo5fica5on
NSDeletedObjectsKey
NSInsertedObjectsKey
NSUpdatedObjectsKey
Valida&on
None
var name = "Kyle" var error:NSError? if person.validateValue( AutoreleasingUnsafeMutablePointer(&name), forKey:"name",
error:&error) { println("\(name) is a valid name.") }
Properga(on
None
Migra&ons
NSMigratePersistentStoresAutoma1callyOp1on
class Person : NSManagedObject {¬ var name:String + var birthdate:NSDate?
}
Components
NSManagedObject
class Person : NSManagedObject { var name:String }
@objc(Person) class Person : NSManagedObject { @NSManaged var name:String }
None
Mogenerator
$ brew install mogenerator
$ mogenerator --model=Model.xcdatamodeld --machine-dir=Model/Machine --human-dir=Model
├── Machine │ ├── _Organisation.swift │ └── _Person.swift ├── Organisation.swift
└── Person.swift
let person:NSManagedObject = ...; person.valueForKey("name")
NSManagedObjectContext
None
NSManagedObjectContext(concurrencyType)
enum NSManagedObjectContextConcurrencyType : UInt { case ConfinementConcurrencyType case PrivateQueueConcurrencyType case
MainQueueConcurrencyType }
context.performBlock { }
context.performBlockAndWait { }
NSPersistentStoreCoordinator
NSPersistentStore
NSSQLiteStoreType
let options = [ NSPersistentStoreUbiquitousContentNameKey: "Posts" ]
NSInMemoryStoreType
Stack
None
None
Performance
None
None
None
None
Locking
Write&Ahead&Locking
None
Boilerplate
KFData/Store
None
Querying
NSFetchRequest • predicate • sortDescriptors
NSFetchRequest • predicate • sortDescriptors • fetchLimit • fetchOffset •
fetchBatchSize • ...
NSSortDescriptor NSSortDescriptor(key: "title", ascending: true)
NSPredicate NSPredicate(format: "author == 'Kyle'")
Every&Ar(cle
Every&Ar(cle • Ordered&by&Title • Wri.en&Kyle
let fetchRequest = NSFetchRequest(entityName: "Article")
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "title", ascending: true)]
fetchRequest.predicate = NSPredicate(format: "author == 'Kyle'")
var error:NSError? let articles = managedObjectContext.executeFetchRequest(fetchRequest, error: &error)
let fetchRequest = NSFetchRequest(entityName: "Article") fetchRequest.sortDescriptors = [NSSortDescriptor(key: "title", ascending:
true)] fetchRequest.predicate = NSPredicate(format: "author == 'Kyle'") var error:NSError? let articles = managedObjectContext.executeFetchRequest(fetchRequest, error: &error)
let fetchRequest = NSFetchRequest(entityName: "Article") fetchRequest.sortDescriptors = [NSSortDescriptor(key: "title", ascending:
true)] fetchRequest.predicate = NSPredicate(format: "author == 'Kyle'") var error:NSError? let articles = managedObjectContext.executeFetchRequest(fetchRequest, error: &error) if let error = error { println("Failed to execute fetch request: \(error)") } else { println("Success") }
"Article" "title" "author == 'Kyle'" .
None
let result = Article.queryset(context) .filter(Article.attributes.author == "Kyle") .orderBy(Article.attributes.title)
None
Asyncronous)Fetching
NSAsyncronousFetchRequest
let request = NSAsyncronousFetchRequest(fetchRequest:fetchRequest) { result in } var error:NSError?
managedObjectContext.executeRequest(request, &error)
Fetched'Results'Controller
// MARK: NSFetchedResultsControllerDelegate func controllerDidChangeContent(controller: NSFetchedResultsController) { tableView.reloadData() } //
MARK: UITableViewDataSource func numberOfSectionsInTableView(tableView: UITableView) -> Int { return fetchedResultsController.sections?.count } func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { let sectionInfo = fetchedResultsController.sections[section] as NSFetchedResultsSectionInfo return sectionInfo.numberOfObjects() } func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { return cell from managed object }
func controllerWillChangeContent(controller: NSFetchedResultsController) { tableView.beginUpdates() } func controller(controller: NSFetchedResultsController, didChangeObject
anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) { // Insert, reload or remove rows } func controllerDidChangeContent(controller: NSFetchedResultsController) { tableView.endUpdates() }
Boilerplate
- (instancetype)initWithTableView:(UITableView *)tableView fetchedResultsController:(NSFetchedResultsController *)fetchedResultsController { NSParameterAssert(tableView != nil); NSParameterAssert(fetchedResultsController
!= nil); if (self = [super init]) { _tableView = tableView; tableView.dataSource = self; _fetchedResultsController = fetchedResultsController; _fetchedResultsController.delegate = self; } return self; } - (instancetype)initWithTableView:(UITableView *)tableView managedObjectContext:(NSManagedObjectContext *)managedObjectContext fetchRequest:(NSFetchRequest *)fetchRequest sectionNameKeyPath:(NSString *)sectionNameKeyPath cacheName:(NSString *)cacheName { NSParameterAssert(managedObjectContext != nil); NSParameterAssert(fetchRequest != nil); NSFetchedResultsController *fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:sectionNameKeyPath cacheName:cacheName]; return [self initWithTableView:tableView fetchedResultsController:fetchedResultsController]; } - (NSManagedObjectContext *)managedObjectContext { return [_fetchedResultsController managedObjectContext]; } - (NSFetchRequest *)fetchRequest { return [_fetchedResultsController fetchRequest]; } - (BOOL)performFetch:(NSError **)error { BOOL result = [self.fetchedResultsController performFetch:error]; [self.tableView reloadData]; return result; } #pragma mark - - (id <NSFetchedResultsSectionInfo>)sectionInfoForSection:(NSUInteger)section { return self.fetchedResultsController.sections[section]; } - (id <NSObject>)objectAtIndexPath:(NSIndexPath *)indexPath { return [self sectionInfoForSection:indexPath.section].objects[indexPath.row]; } #pragma mark - NSFetchedResultsControllerDelegate - (void)controllerWillChangeContent:(NSFetchedResultsController *)controller { [self.tableView beginUpdates]; } - (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type { NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:sectionIndex]; switch(type) { case NSFetchedResultsChangeInsert: [self.tableView insertSections:indexSet withRowAnimation:UITableViewRowAnimationFade]; break; case NSFetchedResultsChangeDelete: [self.tableView deleteSections:indexSet withRowAnimation:UITableViewRowAnimationFade]; break; case NSFetchedResultsChangeUpdate: case NSFetchedResultsChangeMove: break; } } - (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath { switch(type) { case NSFetchedResultsChangeInsert: [self.tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; break; case NSFetchedResultsChangeDelete: [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; break; case NSFetchedResultsChangeUpdate: { [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; break; } case NSFetchedResultsChangeMove: [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; [self.tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; break; } } - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller { [self.tableView endUpdates]; } #pragma mark - UITableViewDataSource - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { NSUInteger count = [self.fetchedResultsController.sections count]; return (NSInteger)count; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { id <NSFetchedResultsSectionInfo> sectionInfo = [self sectionInfoForSection:section]; return (NSInteger)sectionInfo.numberOfObjects; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { if (self.cellForManagedObject == nil) { NSString *reason = [NSString stringWithFormat:@"%@: You must override %@ or set %@", NSStringFromClass([self class]), NSStringFromSelector(@selector(tableView:cellForRowAtIndexPath:)), NSStringFromSelector(@selector(cellForManagedObject))]; @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:reason userInfo:nil]; } NSManagedObject *managedObject = [self objectAtIndexPath:indexPath]; return self.cellForManagedObject(tableView, indexPath, managedObject); } - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { return [[self sectionInfoForSection:section] name]; } - (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section { return nil; } - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { switch (editingStyle) { case UITableViewCellEditingStyleDelete: { NSManagedObject *managedObject = [self objectAtIndexPath:indexPath]; [self.managedObjectContext deleteObject:managedObject]; NSError *error; if ([self.managedObjectContext save:&error] == NO) { NSLog(@"%@: Failed to save managed object context after deleting %@", NSStringFromClass([self class]), error); } break; } case UITableViewCellEditingStyleInsert: break; case UITableViewCellEditingStyleNone: break; } }
UIKit&Data&Sources • Kyle&Fuller:&KFData/UI • Ash&Furrow:&UICollec8onView+NSFetchedResultsController • Sam&Soffes:&SSDataKit
Debugging
let viewController = CCLEntityListViewController(context) presentViewController(viewController, animated:true)
None
!@kylefuller