Has anyone got iCloud core data syncing setup on Xcode 6 and iOS 8? (hopefully this isn't a duplicate post)
Where did iCloud Core Data storage option go?
I remember Core Data had an extra storage option called Core Data storage, but now in Xcode 6 it only seems to show key-value and document storage when I enable the iCloud toggle in Xcode 6.
So far, I don't know if I've setup Core Data iCloud correctly.
Xcode appears to have setup the iCloud containers in the iOS Developer Portal:
iCloud.com.xxxxxx.xxxxxxxx (note: I've replaced the actual strings with xxxx here)
My Xcode 6 iCloud "services" list shows no ticks next to:
Which one should we be using now since it doesn't list "core data" as a storage option?
In the "Containers" directly below the "services", it shows the following options greyed out:
I can't choose any option, it seems to force me to "Use default container".
Finally, Xcode seems to show ticks for:
So by Xcode's own automated process, it setup everything for me.
OK, so I read around and notice a iCloud stack written here:
https://github.com/mluisbrown/iCloudCoreDataStack
I've taken the necessary code and tried to adapt to my Core Data manager singleton:
+ (id)sharedModel; + (ALAssetsLibrary *)sharedLibrary; @property (nonatomic, readonly) NSManagedObjectContext *mainContext; @property (nonatomic, readonly) NSPersistentStoreCoordinator *storeCoordinator; - (NSString *)modelName; - (NSString *)pathToModel; - (NSString *)storeFilename; - (NSString *)pathToLocalStore; #pragma mark - Entity Fetching Methods - -(NSArray *)fetchEntityOfType:(NSString *)entityType UsingPredicated:(NSPredicate *)predicate sortBy:(NSString *)sortKey ascendingOrder:(BOOL)ascendingOrder;
@property (nonatomic, strong) NSManagedObjectModel *managedObjectModel; - (NSString *)documentsDirectory; @end @implementation MLSAlbumsDataModel @synthesize managedObjectModel = _managedObjectModel; @synthesize storeCoordinator = _storeCoordinator; @synthesize mainContext = _mainContext; + (id)sharedModel { static MLSAlbumsDataModel *__instance = nil; if (__instance == nil) { __instance = [[MLSAlbumsDataModel alloc] init]; } return __instance; } + (ALAssetsLibrary *)sharedLibrary { static ALAssetsLibrary *__instance = nil; if (__instance == nil) { __instance = [[ALAssetsLibrary alloc] init]; } return __instance; } - (NSString *)modelName { return @"Albums"; } - (NSString *)pathToModel { return [[NSBundle mainBundle] pathForResource:[self modelName] ofType:@"momd"]; } - (NSString *)storeFilename { return [[self modelName] stringByAppendingPathExtension:@"sqlite"]; } - (NSString *)pathToLocalStore { return [[self documentsDirectory] stringByAppendingPathComponent:[self storeFilename]]; } - (NSString *)documentsDirectory { NSString *documentsDirectory = nil; NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); documentsDirectory = [paths objectAtIndex:0]; return documentsDirectory; } - (NSManagedObjectContext *)mainContext { if(_mainContext == nil) { _mainContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; _mainContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy; // setup persistent store coordinator DLog(@"SQLITE STORE PATH: %@", [self pathToLocalStore]); NSURL *storeURL = [NSURL fileURLWithPath:[self pathToLocalStore]]; //_mainContext.persistentStoreCoordinator = [self storeCoordinator]; _mainContext.persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:self.managedObjectModel]; __weak NSPersistentStoreCoordinator *psc = self.mainContext.persistentStoreCoordinator; // iCloud notification subscriptions NSNotificationCenter *dc = [NSNotificationCenter defaultCenter]; [dc addObserver:self selector:@selector(storesWillChange:) name:NSPersistentStoreCoordinatorStoresWillChangeNotification object:psc]; [dc addObserver:self selector:@selector(storesDidChange:) name:NSPersistentStoreCoordinatorStoresDidChangeNotification object:psc]; [dc addObserver:self selector:@selector(persistentStoreDidImportUbiquitousContentChanges:) name:NSPersistentStoreDidImportUbiquitousContentChangesNotification object:psc]; NSError* error; // the only difference in this call that makes the store an iCloud enabled store // is the NSPersistentStoreUbiquitousContentNameKey in options. I use "iCloudStore" // but you can use what you like. For a non-iCloud enabled store, I pass "nil" for options. // Note that the store URL is the same regardless of whether you're using iCloud or not. // If you create a non-iCloud enabled store, it will be created in the App's Documents directory. // An iCloud enabled store will be created below a directory called CoreDataUbiquitySupport // in your App's Documents directory [self.mainContext.persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:@{ NSPersistentStoreUbiquitousContentNameKey : @"iCloudStore" } error:&error]; if (error) { NSLog(@"error: %@", error); } _storeCoordinator = self.mainContext.persistentStoreCoordinator; } return _mainContext; } - (NSManagedObjectModel *)managedObjectModel { if(_managedObjectModel == nil) { NSURL *storeURL = [NSURL fileURLWithPath:[self pathToModel]]; _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:storeURL]; } return _managedObjectModel; } - (NSPersistentStoreCoordinator *)storeCoordinator { if (_storeCoordinator == nil) { // ----------------------------------------------------------------------------------------------------------------------------- // Code moved to managed object context code above // ----------------------------------------------------------------------------------------------------------------------------- /* DLog(@"SQLITE STORE PATH: %@", [self pathToLocalStore]); NSURL *storeURL = [NSURL fileURLWithPath:[self pathToLocalStore]]; NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil]; NSError *error = nil; if (![psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) { NSDictionary *userInfo = [NSDictionary dictionaryWithObject:error forKey:NSUnderlyingErrorKey]; NSString *reason = @"Could not create persistent store"; NSException *exc = [NSException exceptionWithName:NSInternalInconsistencyException reason:reason userInfo:userInfo]; @throw exc; } _storeCoordinator = psc; */ } return _storeCoordinator; } #pragma mark - iCloud Related Methods - // Subscribe to NSPersistentStoreDidImportUbiquitousContentChangesNotification - (void)persistentStoreDidImportUbiquitousContentChanges:(NSNotification*)note { NSLog(@"%s", __PRETTY_FUNCTION__); NSLog(@"%@", note.userInfo.description); NSManagedObjectContext *moc = self.mainContext; [moc performBlock:^{ [moc mergeChangesFromContextDidSaveNotification:note]; DLog(@"NSPersistentStoreDidImportUbiquitousContentChangesNotification executed"); /* // you may want to post a notification here so that which ever part of your app // needs to can react appropriately to what was merged. // An exmaple of how to iterate over what was merged follows, although I wouldn't // recommend doing it here. Better handle it in a delegate or use notifications. // Note that the notification contains NSManagedObjectIDs // and not NSManagedObjects. NSDictionary *changes = note.userInfo; NSMutableSet *allChanges = [NSMutableSet new]; [allChanges unionSet:changes[NSInsertedObjectsKey]]; [allChanges unionSet:changes[NSUpdatedObjectsKey]]; [allChanges unionSet:changes[NSDeletedObjectsKey]]; for (NSManagedObjectID *objID in allChanges) { // do whatever you need to with the NSManagedObjectID // you can retrieve the object from with [moc objectWithID:objID] } */ }]; } // Subscribe to NSPersistentStoreCoordinatorStoresWillChangeNotification // most likely to be called if the user enables / disables iCloud // (either globally, or just for your app) or if the user changes // iCloud accounts. - (void)storesWillChange:(NSNotification *)note { NSManagedObjectContext *moc = self.mainContext; [moc performBlockAndWait:^{ NSError *error = nil; if ([moc hasChanges]) { [moc save:&error]; } [moc reset]; }]; // now reset your UI to be prepared for a totally different // set of data (eg, popToRootViewControllerAnimated:) // but don't load any new data yet. [[NSNotificationCenter defaultCenter] postNotificationName:@"notifCoreDataStoreWillChange" object:nil]; DLog(@"storeWillChange notification fire"); } // Subscribe to NSPersistentStoreCoordinatorStoresDidChangeNotification - (void)storesDidChange:(NSNotification *)note { // here is when you can refresh your UI and // load new data from the new store [[NSNotificationCenter defaultCenter] postNotificationName:@"notifCoreDataStoreDidChange" object:nil]; DLog(@"storeDidChange notification fire"); } #pragma mark - Entity Fetching Methods - -(NSArray *)fetchEntityOfType:(NSString *)entityType UsingPredicated:(NSPredicate *)predicate sortBy:(NSString *)sortKey ascendingOrder:(BOOL)ascendingOrder { NSEntityDescription *entityDescription = [NSEntityDescription entityForName:entityType inManagedObjectContext:[[MLSAlbumsDataModel sharedModel] mainContext]]; NSSortDescriptor *sortDescriptor = nil; if(sortKey) { sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortKey ascending:ascendingOrder]; } else { sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"updatedAt" ascending:ascendingOrder]; } NSFetchRequest *request = [[NSFetchRequest alloc] init]; request.entity = entityDescription; if(predicate) { request.predicate = predicate; } request.sortDescriptors = @[sortDescriptor]; NSError *error = nil; NSArray *results = [[[MLSAlbumsDataModel sharedModel] mainContext] executeFetchRequest:request error:&error]; if(results == nil) { DLog(@"Error getting entity of type '%@' using predicate '%@', sortKey '%@' ascendingOrder %d", entityType, predicate, sortKey, ascendingOrder); } return results; }
I tried to run the app on the iPad Simulator (I believe it is the iOS 8 simulator) and on iPad device running iOS 7.x
I created an album with a user entered name on the simulator, but I am not seeing the iPad device showing the newly created album. I also tried reversing the roles, iPad device create, iOS simulator no results either.
I do see my log messages:
storeDidChange notification fire SQLITE STORE PATH: /Users/xxxxxxx/Library/Developer/CoreSimulator/Devices/3DC17576-92E9-4EAF-B77A-41340AE28F92/data/Containers/Data/Application/E51085CE-3772-4DF1-A503-1C243497091A/Documents/Albums.sqlite
If I minimise the app in the simulator and open it again (without pressing the Stop button in Xcode), I see these message:
-[PFUbiquitySwitchboardEntryMetadata setUseLocalStorage:](808): CoreData: Ubiquity: nobody~sim301AE3E8-16B2-5A08-917D-7B55D1879BE4:iCloudStore Using local storage: 1
I read that "Using local storage: 0" is what it should ideally be? and that 1 means local device data store rather than iCloud data store.
When I create an album, save it, stop the simulator, then start the app again, my albums disappears, but immediately after I create a new album, all the previous album reappear magically again. It's a bit odd. If I don't use iCloud and revert my code to previous setup, I can create and see my album fine, regardless of whether I minimise my app or not, or restart app, but then I don't have iCloud sync which I need.
Have I made any mistakes anywhere?
Sorry for the long post but has anyone got iCloud working for iOS 8 and Xcode 6 ?
I could really use some help.
1) Does iOS 8 require the use of this container identifier ? (which Xcode 6 generated for me):
com.apple.developer.icloud-container-identifiers
That's not what the iOS 7 one looks like right? iOS 7 one is more like:
com.apple.developer.ubiquity-container-identifiers
2) Do I need an iCloud Drive account before it works?
Super confused @_@
I struggled with a similar issue. I would see:
Using local storage: 1
but no other output. And if I rebuilt the app I would get something like:
Error adding store for new account:
One thing to note is that I would only get this output if I first presses the "home button" on the iPhone, and then reopened the app.
A key thing to note is that I had no services selected. To fix this issue, I selected "iCloud Documents".
You may need to delete the app before rebuilding.
OK...then....lol. I think I solved it.
New discovery. After skimming through this page:
http://www.tuaw.com/2014/09/17/psa-do-not-upgrade-to-icloud-drive-during-ios-8-installation/
It says:
iCloud Drive is Apple's new and improved iCloud syncing and file storage feature that allows you to share documents between your iOS 8 devices and your Mac running OS X 10 Yosemite.
So, I decided to bite the bullet and upgrade my iCloud account to iCloud drive (free to upgrade).
After upgrading to iCloud drive, and re-ran my app with a few Xcode 6 changes, it's working now.
Some Important Things to note:
For the above reason, I changed to using a Ubiquity container with this pattern:
iCloud.$(CFBundleIdentifier)
So something like:
iCloud.com.xxxxxxxx.iCloudCoreDataDemo
Where "xxxxxxxx" is my company name identifier.
I made the above iCloud container by logging into my iOS Developer Center, perhaps you could just press the "+" sign inside Xcode 6 and enter one there, Xcode should automagically setup everything for you.
One block of code I used to test to see if it's working is this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.persistentStack = [[PersistentStack alloc] initWithStoreURL:self.storeURL modelURL:self.modelURL]; self.managedObjectContext = self.persistentStack.managedObjectContext; NSURL *containerURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:@"iCloud.com.xxxxxxxxxx.iCloudCoreDataDemo"]; if(containerURL == nil) { NSLog(@"containerURL == nil"); } else { NSLog(@"hurray?"); } return YES; }
If you see "hurray?" then it's fine, you should also see this pattern of text in your Xcode console output:
2014-10-07 17:37:23.196 iCloudCoreDataDemo[8104:130250] documentsDirectory = file:///Users/xxxxxxxx/Library/Developer/CoreSimulator/Devices/9FAFE881-13CA-4608-8BE6-728C793FAFFB/data/Containers/Data/Application/BC6CA07D-605A-4927-94AF-E9E21E204D2B/Documents/ 2014-10-07 17:37:23.386 iCloudCoreDataDemo[8104:130250] storeDidChange 2014-10-07 17:37:23.390 iCloudCoreDataDemo[8104:130250] -[PFUbiquitySwitchboardEntryMetadata setUseLocalStorage:](808): CoreData: Ubiquity: nobody~sim301AE3E8-16B2-5A08-917D-7B55D1879BE4:iCloudStore Using local storage: 1 2014-10-07 17:37:23.402 iCloudCoreDataDemo[8104:130250] hurray? 2014-10-07 17:37:33.909 iCloudCoreDataDemo[8104:130250] storeWillChange 2014-10-07 17:37:33.933 iCloudCoreDataDemo[8104:130250] storeDidChange 2014-10-07 17:37:33.933 iCloudCoreDataDemo[8104:130330] -[PFUbiquitySwitchboardEntryMetadata setUseLocalStorage:](808): CoreData: Ubiquity: nobody~sim301AE3E8-16B2-5A08-917D-7B55D1879BE4:iCloudStore Using local storage: 0
Notice the two important lines:
Using local storage: 1
later becomes:
Using local storage: 0
Local storage 1 means it's currently using local storage, while local storage 0 means it has moved the data to iCloud storage.
I hope this benefits everyone else.
OK, so I've just discovered something and managed to get it working for iOS 7 only. I still haven't figured out how to do it in iOS 8 but I have noticed something important.
On my iPhone 5 running iOS 8.0.2, I don't have the "Document & Data" option inside the iCloud settings menu anymore.
However, on my iPad running iOS 7, I DO see the "Document & Data" options.
Perhaps this is the reason why it doesn't work on iOS 8, we no longer have Document & Data storage ?
Anyhow, here's what I discovered for iOS 7 only solution.
I found this page here
https://developer.apple.com/library/ios/documentation/General/Conceptual/iCloudDesignGuide/Chapters/iCloudFundametals.html
and one of the line says:
Sure enough, I went into my Xcode 6 project file and ticked the "iCloud Documents" option. This un-greyed the radio buttons, but I still left it at "Use default Containers".
One thing I learned is that I need to init my PersistentStack in the appDelegate. Previously, I tried to init the persistent stack inside the +(id)sharedInstance method but it caused the iCloud to only sync the first time, so after initial load and sync, adding new record doesn't get synced afterwards.
I rewrote a basic app and modified the persistent stack slightly:
#import <UIKit/UIKit.h> #import "PersistentStack.h" @interface AppDelegate : UIResponder <UIApplicationDelegate> @property (strong, nonatomic) UIWindow *window; @property (nonatomic, strong) NSManagedObjectContext* managedObjectContext; @property (nonatomic, strong) PersistentStack* persistentStack; @end
@interface AppDelegate () @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.persistentStack = [[PersistentStack alloc] initWithStoreURL:self.storeURL modelURL:self.modelURL]; self.managedObjectContext = self.persistentStack.managedObjectContext; return YES; } ... - (NSURL*)storeURL { NSURL* documentsDirectory = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:NULL]; return [documentsDirectory URLByAppendingPathComponent:@"MyApp.sqlite"]; } - (NSURL*)modelURL { return [[NSBundle mainBundle] URLForResource:@"MyApp" withExtension:@"momd"]; }
#import <Foundation/Foundation.h> #import <CoreData/CoreData.h> #import "Book.h" #import <UIKit/UIKit.h> @interface PersistentStack : NSObject +(id)sharedInstance; - (id)initWithStoreURL:(NSURL *)storeURL modelURL:(NSURL *)modelURL; @property (nonatomic,strong,readonly) NSManagedObjectContext *managedObjectContext; #pragma mark - Regular Methods - -(Book *)insertNewBookWithDate:(NSDate *)newDate; -(void)deleteBook:(Book *)book; -(NSArray *)fetchEntityOfType:(NSString *)entityType withPredicate:(NSPredicate *)predicate andSortKey:(NSString *)sortKey; @end
#import "PersistentStack.h" #import "AppDelegate.h" @interface PersistentStack () @property (nonatomic,strong,readwrite) NSManagedObjectContext* managedObjectContext; @property (nonatomic,strong) NSURL* modelURL; @property (nonatomic,strong) NSURL* storeURL; @end @implementation PersistentStack +(id)sharedInstance { static PersistentStack *sharedInstance = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate; sharedInstance = appDelegate.persistentStack; }); return sharedInstance; } - (id)initWithStoreURL:(NSURL*)storeURL modelURL:(NSURL*)modelURL { self = [super init]; if (self) { self.storeURL = storeURL; self.modelURL = modelURL; [self setupManagedObjectContext]; } return self; } - (void)setupManagedObjectContext { self.managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; self.managedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy; self.managedObjectContext.persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:self.managedObjectModel]; //__weak NSPersistentStoreCoordinator *psc = self.managedObjectContext.persistentStoreCoordinator; // iCloud notification subscriptions NSNotificationCenter *dc = [NSNotificationCenter defaultCenter]; [dc addObserver:self selector:@selector(storesWillChange:) name:NSPersistentStoreCoordinatorStoresWillChangeNotification object:self.managedObjectContext.persistentStoreCoordinator]; [dc addObserver:self selector:@selector(storesDidChange:) name:NSPersistentStoreCoordinatorStoresDidChangeNotification object:self.managedObjectContext.persistentStoreCoordinator]; [dc addObserver:self selector:@selector(persistentStoreDidImportUbiquitousContentChanges:) name:NSPersistentStoreDidImportUbiquitousContentChangesNotification object:self.managedObjectContext.persistentStoreCoordinator]; NSError* error; // the only difference in this call that makes the store an iCloud enabled store // is the NSPersistentStoreUbiquitousContentNameKey in options. I use "iCloudStore" // but you can use what you like. For a non-iCloud enabled store, I pass "nil" for options. // Note that the store URL is the same regardless of whether you're using iCloud or not. // If you create a non-iCloud enabled store, it will be created in the App's Documents directory. // An iCloud enabled store will be created below a directory called CoreDataUbiquitySupport // in your App's Documents directory [self.managedObjectContext.persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:self.storeURL options:@{ NSPersistentStoreUbiquitousContentNameKey : @"iCloudStore" } error:&error]; if (error) { NSLog(@"error: %@", error); } } - (NSManagedObjectModel*)managedObjectModel { return [[NSManagedObjectModel alloc] initWithContentsOfURL:self.modelURL]; } // Subscribe to NSPersistentStoreDidImportUbiquitousContentChangesNotification - (void)persistentStoreDidImportUbiquitousContentChanges:(NSNotification*)note { NSLog(@"%s", __PRETTY_FUNCTION__); NSLog(@"%@", note.userInfo.description); NSManagedObjectContext *moc = self.managedObjectContext; [moc performBlock:^{ [moc mergeChangesFromContextDidSaveNotification:note]; [[NSNotificationCenter defaultCenter] postNotificationName:@"notifiCloudStoreDidChange" object:nil]; /* // you may want to post a notification here so that which ever part of your app // needs to can react appropriately to what was merged. // An exmaple of how to iterate over what was merged follows, although I wouldn't // recommend doing it here. Better handle it in a delegate or use notifications. // Note that the notification contains NSManagedObjectIDs // and not NSManagedObjects. NSDictionary *changes = note.userInfo; NSMutableSet *allChanges = [NSMutableSet new]; [allChanges unionSet:changes[NSInsertedObjectsKey]]; [allChanges unionSet:changes[NSUpdatedObjectsKey]]; [allChanges unionSet:changes[NSDeletedObjectsKey]]; for (NSManagedObjectID *objID in allChanges) { // do whatever you need to with the NSManagedObjectID // you can retrieve the object from with [moc objectWithID:objID] } */ }]; } // Subscribe to NSPersistentStoreCoordinatorStoresWillChangeNotification // most likely to be called if the user enables / disables iCloud // (either globally, or just for your app) or if the user changes // iCloud accounts. - (void)storesWillChange:(NSNotification *)note { NSLog(@"storeWillChange"); NSManagedObjectContext *moc = self.managedObjectContext; //[moc performBlockAndWait:^{ [moc performBlock:^{ NSError *error = nil; if ([moc hasChanges]) { [moc save:&error]; } [moc reset]; }]; // now reset your UI to be prepared for a totally different // set of data (eg, popToRootViewControllerAnimated:) // but don't load any new data yet. } // Subscribe to NSPersistentStoreCoordinatorStoresDidChangeNotification - (void)storesDidChange:(NSNotification *)note { // here is when you can refresh your UI and // load new data from the new store NSLog(@"storeDidChange"); [[NSNotificationCenter defaultCenter] postNotificationName:@"notifiCloudStoreDidChange" object:nil]; } #pragma mark - Regular Methods - -(Book *)insertNewBookWithDate:(NSDate *)newDate { Book *newBook = [NSEntityDescription insertNewObjectForEntityForName:@"Book" inManagedObjectContext:self.managedObjectContext]; newBook.bookName = @"Book"; newBook.publishDate = newDate; [self.managedObjectContext save:nil]; return newBook; } -(void)deleteBook:(Book *)book { [self.managedObjectContext deleteObject:book]; [self.managedObjectContext save:nil]; } -(NSArray *)fetchEntityOfType:(NSString *)entityType withPredicate:(NSPredicate *)predicate andSortKey:(NSString *)sortKey { NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; NSEntityDescription *entity = [NSEntityDescription entityForName:entityType inManagedObjectContext:self.managedObjectContext]; [fetchRequest setEntity:entity]; // Specify criteria for filtering which objects to fetch [fetchRequest setPredicate:predicate]; // Specify how the fetched objects should be sorted NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortKey ascending:YES]; [fetchRequest setSortDescriptors:[NSArray arrayWithObjects:sortDescriptor, nil]]; NSError *error = nil; NSArray *fetchedObjects = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error]; if (fetchedObjects == nil) { NSLog(@"couldn't fetch entity of type '%@', error: %@", entityType, error.localizedDescription); } return fetchedObjects; } @end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With