Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
ICYMI: Core Data at CMD+R 2014
Search
Kyle Fuller
October 22, 2014
Technology
360
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
160
Preparing for the future of API Description Languages
kylef
0
140
Resilient API Design
kylef
1
380
Building a Swift Web API and Application Together
kylef
2
2.2k
Testing without Xcode - CMD+U 2016
kylef
0
300
End-to-end: Building a Web Service in Swift (MCE 2016)
kylef
2
520
Designing APIs for Humans - Write the Docs 2016
kylef
0
380
Embracing Change - MBLTDev 2015
kylef
3
720
Practical Declarative Programming (360 iDev 2015)
kylef
3
570
Other Decks in Technology
See All in Technology
事業活動を AI Ready にする攻めと守りのデータエンジニアリング / data-engineering-for-ai-ready-business
pei0804
1
200
個別開発で終わらせない。 現場の課題をプロダクトの強さに変える StockmarkのFDE
ktkrhr
0
590
BedrockとLambdaで作る リアルタイム進行型推理ゲーム
kawametho
0
190
freeeらしさをAIとともに作る / Creating the freee Experience with AI
ymrl
0
200
Meet AgentCore Identity Consent Portal
hironobuiga
3
190
並行性の問題を防げ!実践トランザクション入門
occhi
0
260
データ品質を壊しながらSnowflakeのAIに分析させてみた
kawanago
0
510
雪かき部 #7 もう怖くない!SELECT文!
foursue
0
280
[2026 Oracle Technical Deep Dive] OCI AI Resilience -OCIのセキュリティ対策機能をきちんと使いこなす- (2026年9月17日開催)
oracle4engineer
PRO
0
130
営業オントロジーの作り方と、エージェントからの辿り方 ── ナレッジワークの現場から
kworkdev
PRO
1
270
FactoryBotアンチパターン / factory_bot anti-patterns
toshimaru
0
130
【データ横丁主催】AI Agentがコンテキストを使って仕事をした後、何が残るのか― 組織の経験を次の判断に引き継ぐ「Agent Memory」
shisyu_gaku
2
330
Featured
See All Featured
4 Signs Your Business is Dying
shpigford
187
23k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
The AI Search Optimization Roadmap by Aleyda Solis
aleyda
2
6.3k
AI: The stuff that nobody shows you
jnunemaker
PRO
10
1.1k
The SEO identity crisis: Don't let AI make you average
varn
0
580
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
840
We Have a Design System, Now What?
morganepeng
55
8.4k
How to Think Like a Performance Engineer
csswizardry
28
2.9k
SEOcharity - Dark patterns in SEO and UX: How to avoid them and build a more ethical web
sarafernandez
0
300
Documentation Writing (for coders)
carmenintech
77
5.6k
The AI Revolution Will Not Be Monopolized: How open-source beats economies of scale, even for LLMs
inesmontani
PRO
3
3.8k
Kristin Tynski - Automating Marketing Tasks With AI
techseoconnect
PRO
0
540
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