Guest User

Untitled

a guest
Jan 20th, 2015
351
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.68 KB | None | 0 0
  1. //
  2. // SettingsViewController+BackupRestore.m
  3. // SalonBook
  4. //
  5. // Created by Rolf Marsh on 1/18/15.
  6. // Copyright (c) 2015 Prager, Software. All rights reserved.
  7. //
  8.  
  9. #import "SettingsViewController+BackupRestore.h"
  10.  
  11. @implementation SettingsViewController (BackupRestore)
  12.  
  13. NSURL *sqliteStoreURL;
  14. NSURL *backupFileURL;
  15.  
  16. //NSManagedObjectModel *managedObjectModel;
  17. NSManagedObjectModel *_managedObjectModel;
  18. //NSManagedObjectContext *managedObjectContext;
  19. NSManagedObjectContext *_managedObjectContext;
  20. NSPersistentStoreCoordinator *persistentStoreCoordinator;
  21. NSPersistentStoreCoordinator *_persistentStoreCoordinator;
  22. NSDictionary *localStoreOptions;
  23. //BOOL isOpening;
  24. //BOOL userICloudChoice = NO;
  25.  
  26. BOOL _import_or_save;
  27. BOOL _storesChanging;
  28. BOOL _job_counter;
  29. //BOOL _use_old_model;
  30.  
  31.  
  32. NSString* const OSStoreChangeNotification = @"OSCoreDataStoreChanged";
  33.  
  34.  
  35.  
  36.  
  37. #pragma mark - backupLocalStore
  38. - (NSURL *)backupLocalStore {
  39.  
  40. NSError *error;
  41.  
  42. // create documentsDirectoryURL
  43. NSURL *documentsDirectory = [[[NSFileManager defaultManager]
  44. URLsForDirectory:NSDocumentDirectory
  45. inDomains:NSUserDomainMask]
  46. lastObject];
  47.  
  48. // create storeURL
  49. sqliteStoreURL = [documentsDirectory URLByAppendingPathComponent:@"saori.sqlite"];
  50.  
  51. // create backupFileURL
  52. NSDateFormatter *dateFormatter = [NSDateFormatter new];
  53. dateFormatter.dateFormat = @"yyyymmddHHmmss";
  54. NSString *localDateString = [dateFormatter stringFromDate:[NSDate date]];
  55. backupFileURL = [documentsDirectory URLByAppendingPathComponent:[NSString stringWithFormat: @"saori.backup-%@",localDateString]];
  56.  
  57.  
  58. // create managedObjectModel and a PersistentStoreCoordinator
  59. NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"salonbook" ofType:@"momd"];
  60. NSURL *modelURL = [NSURL fileURLWithPath: modelPath];
  61. NSManagedObjectModel *managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL: modelURL];
  62. persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: managedObjectModel];
  63.  
  64.  
  65. // Open the store
  66. localStoreOptions = @{NSSQLitePragmasOption:@{@"journal_mode":@"WAL"}};
  67. id sourceStore = [persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
  68. configuration:nil
  69. URL: sqliteStoreURL
  70. options: localStoreOptions
  71. error:&error];
  72.  
  73. if(!sourceStore) { // if persistentStoreCoordinator was NOT created...
  74.  
  75. NSLog(@"\n\nfailed to add old store");
  76. persistentStoreCoordinator = nil;
  77. return nil;
  78. }
  79. else {
  80.  
  81. NSLog(@"\n\nSuccessfully added store to migrate; About to migrate the store... ");
  82.  
  83. id successfulBackup = [persistentStoreCoordinator migratePersistentStore:sourceStore
  84. toURL:backupFileURL
  85. options:localStoreOptions
  86. withType:NSSQLiteStoreType
  87. error: &error]; // was &error
  88.  
  89. if (successfulBackup) {
  90.  
  91. // check for both files
  92. NSFileManager *fm = [[NSFileManager alloc] init];
  93. if( [fm fileExistsAtPath:[sqliteStoreURL path]])
  94. NSLog(@"\n\nsqliteStore exists");
  95. else
  96. NSLog(@"\n\nsqliteStore does NOT exist");
  97.  
  98. if( [fm fileExistsAtPath:[backupFileURL path]])
  99. NSLog(@"\n\nbackupFileURL exists");
  100. else
  101. NSLog(@"\n\nbackupFile does NOT exist");
  102.  
  103.  
  104. NSLog(@"\n\nstore successfully backed up to %@",backupFileURL);
  105. // change file permissions (r+w)
  106.  
  107.  
  108. persistentStoreCoordinator = nil;
  109.  
  110. // now, store it in NSUserDefaults
  111. NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
  112. NSMutableDictionary *preferencesDict = [[userDefaults dictionaryForKey:@"preferencesDictionary"] mutableCopy];
  113.  
  114. [preferencesDict setObject: [backupFileURL absoluteString] forKey:@"backupURL"];
  115. [userDefaults setObject: preferencesDict forKey:@"preferencesDictionary"];
  116. [userDefaults synchronize];
  117.  
  118. return backupFileURL;
  119. }
  120. else {
  121. NSLog(@"\n\nFailed to backup store: %@, %@", error, error.userInfo);
  122. persistentStoreCoordinator = nil;
  123. return nil;
  124. }
  125. }
  126.  
  127. persistentStoreCoordinator = nil;
  128. return nil;
  129. }
  130.  
  131.  
  132. #pragma mark - restoreFile
  133. - (BOOL)restoreBackupFile:(NSURL *)backupFileURL { // @param fileURL: The URL for the file to use.
  134.  
  135. NSError *error;
  136.  
  137. NSURL *documentsDirectory = [[[NSFileManager defaultManager]
  138. URLsForDirectory:NSDocumentDirectory
  139. inDomains:NSUserDomainMask]
  140. lastObject];
  141.  
  142. NSURL *currentCoreDataURL = [documentsDirectory URLByAppendingPathComponent:@"saori.sqlite"];
  143.  
  144. NSLog(@"\n\n currentURL is %@", currentCoreDataURL); // current URL of saori.sqlite
  145. NSLog(@"\n\nbackup file URL to use is %@", backupFileURL); // backup file URL
  146.  
  147. // Close the current store and delete it
  148. _persistentStoreCoordinator = nil;
  149. _managedObjectContext = nil;
  150.  
  151. error = nil;
  152. NSFileManager *fm = [[NSFileManager alloc] init];
  153.  
  154. #pragma mark - TODO **
  155. // check for both files
  156. if( [fm fileExistsAtPath:[currentCoreDataURL path]])
  157. NSLog(@"\n\ncurrentCoreData exists");
  158. else
  159. NSLog(@"\n\n-->currentCoreData does NOT exist");
  160.  
  161. if( [fm fileExistsAtPath:[backupFileURL path]])
  162. NSLog(@"\n\nbackupFile exists");
  163. else {
  164. NSLog(@"\n\n-->backupFile does NOT exist"); // find out why (and automatically do a backup????) displayAlert
  165. return NO;
  166. }
  167.  
  168. // Delete the current store file
  169. if ([fm fileExistsAtPath:[currentCoreDataURL path]]) {
  170. NSLog(@"\n\ntarget file exists");
  171.  
  172. if (![fm removeItemAtURL:currentCoreDataURL error:&error]) { // if the current file is not there...
  173. NSLog(@"\n\nError unable to remove current store file");
  174. NSLog(@"Error removing item Error: %@, %@", error, error.userInfo);
  175. return FALSE;
  176. }
  177. else {
  178. NSLog(@" current store file removed");
  179. }
  180. }
  181. #pragma mark - TODO **
  182.  
  183. BOOL copySuccess = [fm copyItemAtPath:[backupFileURL path] //simply copy the file
  184. toPath:[currentCoreDataURL path]
  185. error:&error];
  186. if (copySuccess) {
  187. NSLog(@" replaced current store file successfully"); // set msg under buttons TODO **
  188. [self openPersistentStore]; // Now open the store again
  189. return TRUE;
  190. }
  191. else {
  192. NSLog(@"Error copying items Error: %@, %@", error, error.userInfo); // change this to alertView
  193. return FALSE;
  194. }
  195.  
  196. }
  197.  
  198.  
  199.  
  200. #pragma mark - openPersistentStore
  201. - (void) openPersistentStore {
  202.  
  203. // isOpening = YES;
  204. NSError *error = nil;
  205. NSPersistentStoreCoordinator *aPersistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
  206.  
  207.  
  208. NSLog(@" store Options are %@", localStoreOptions);
  209.  
  210. // [self registerForStoreChanges: aPersistentStoreCoordinator];
  211.  
  212. // NSLog(@" addPersistentStoreWithType about to be called... ");
  213. // sleep(1); // wait a second...
  214.  
  215. if (![aPersistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL: sqliteStoreURL options: localStoreOptions error:&error]) {
  216.  
  217. NSLog(@" addPersistentStoreWithType failed... ");
  218. NSLog(@" error %@, %@", error, [error userInfo]);
  219. return ;
  220. }
  221.  
  222. NSLog(@" addPersistentStoreWithType completed successfully... ");
  223. _persistentStoreCoordinator = aPersistentStoreCoordinator;
  224.  
  225.  
  226. NSURL *url = [[[_persistentStoreCoordinator persistentStores] objectAtIndex:0] valueForKey:@"URL"];
  227.  
  228. NSLog(@" STORE FILE is %@", [url path]);
  229.  
  230.  
  231. // isOpening = NO;
  232.  
  233. }
  234.  
  235.  
  236.  
  237. #pragma mark - persistentStoreCoordinator
  238. // Returns the persistent store coordinator for the application.
  239. // If the coordinator doesn't already exist, it is created and the application's store added to it.
  240. - (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
  241.  
  242. if (_persistentStoreCoordinator != nil) {
  243. return _persistentStoreCoordinator;
  244. }
  245.  
  246. return _persistentStoreCoordinator;
  247.  
  248. NSError *error = nil;
  249. _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
  250.  
  251. if (sqliteStoreURL == nil) {
  252. NSLog(@" error storeURL is nil!");
  253. return nil;
  254. }
  255.  
  256. NSLog(@" addPersistentStoreWithType about to be called... ");
  257.  
  258. if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL: sqliteStoreURL options: localStoreOptions error:&error]) {
  259. /*
  260. Replace this implementation with code to handle the error appropriately.
  261.  
  262. abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
  263.  
  264. Typical reasons for an error here include:
  265. * The persistent store is not accessible;
  266. * The schema for the persistent store is incompatible with current managed object model.
  267. Check the error message to determine what the actual problem was.
  268.  
  269.  
  270. If the persistent store is not accessible, there is typically something wrong with the file path. Often, a file URL is pointing into the application's resources directory instead of a writeable directory.
  271.  
  272. If you encounter schema incompatibility errors during development, you can reduce their frequency by:
  273. * Simply deleting the existing store:
  274. [[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil]
  275.  
  276. * Performing automatic lightweight migration by passing the following dictionary as the options parameter:
  277. @{NSMigratePersistentStoresAutomaticallyOption:@YES, NSInferMappingModelAutomaticallyOption:@YES}
  278.  
  279. Lightweight migration will only work for a limited set of schema changes; consult "Core Data Model Versioning and Data Migration Programming Guide" for details.
  280.  
  281. */
  282. NSLog(@" addPersistentStoreWithType failed... ");
  283. NSLog(@" error %@, %@", error, [error userInfo]);
  284. return nil;
  285. }
  286.  
  287. NSLog(@" addPersistentStoreWithType completed successfully... ");
  288.  
  289. [self registerForStoreChanges:_persistentStoreCoordinator];
  290.  
  291. return _persistentStoreCoordinator;
  292. }
  293.  
  294.  
  295. #pragma mark - storesDidSave
  296. // NB - this may be called from a background thread so make sure we run on the main thread !!
  297. // This is when transaction logs are loaded
  298. - (void)storesDidSave:(NSNotification*)notification {
  299.  
  300. // Ignore any notifications from the main thread because we only need to merge data
  301. // loaded from other threads.
  302. if ([NSThread isMainThread]) {
  303. NSLog(@" main thread saved context");
  304. return;
  305. }
  306.  
  307. [[NSOperationQueue mainQueue] addOperationWithBlock:^ {
  308. NSLog(@"storesDidSave ");
  309. // Set this so that after the timer goes off we perform a save
  310. // - without this the deletes don't appear to trigger the fetchedResultsController delegate methods !
  311. _import_or_save = YES;
  312.  
  313. // [self createTimer];
  314. if (self.managedObjectContext) {
  315. [self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
  316. }
  317.  
  318. }];
  319. }
  320.  
  321.  
  322.  
  323. #pragma mark - managedObjectContext
  324. // Returns the managed object context for the application.
  325. // If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
  326. - (NSManagedObjectContext *)managedObjectContext {
  327.  
  328. // defaultContext = [NSManagedObjectContext MR_defaultContext]; // set default NSManagedObjectContext for MagicalRecord (from AppDelegate.m)
  329.  
  330.  
  331. // if (_managedObjectContext != nil) {
  332. // return _managedObjectContext;
  333. // }
  334. if(defaultContext != nil)
  335. return defaultContext;
  336.  
  337. NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
  338. if (coordinator != nil) {
  339. // _managedObjectContext = [[NSManagedObjectContext alloc] init];
  340. // Register for saves in order to merge any data from background threads
  341. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(storesDidSave:) name: NSManagedObjectContextDidSaveNotification object: defaultContext];
  342.  
  343. [_managedObjectContext setPersistentStoreCoordinator:coordinator];
  344. }
  345.  
  346. return _managedObjectContext; // is nil? <-------------
  347. }
  348.  
  349.  
  350. //#pragma mark - saveContext
  351. //- (void)saveContext
  352. //{
  353. // if (isOpening) {
  354. // NSLog(@" application is still busy opening!");
  355. // return;
  356. // }
  357. //
  358. // NSError *error = nil;
  359. // NSManagedObjectContext *managedObjectContext = [self managedObjectContext]; // ??????????? is this needed?
  360. // if (managedObjectContext != nil) {
  361. // if ([managedObjectContext hasChanges]) {
  362. //
  363. // if (![managedObjectContext save:&error]) {
  364. // NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
  365. //
  366. // }
  367. // // else {
  368. // // // if we are iCloud enabled then show the network indicator because
  369. // // // we expect to see log files uploaded after this
  370. // // if ([isCloudEnabled])
  371. // // [self showBackgroundTaskActive];
  372. // // }
  373. // }
  374. // }
  375. //}
  376.  
  377.  
  378. //#pragma mark - showBackgroundTaskActive
  379. //- (void)showBackgroundTaskActive {
  380. //
  381. // _job_counter++;
  382. //
  383. // if ([NSThread isMainThread]) {
  384. // [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
  385. // } else {
  386. // dispatch_async(dispatch_get_main_queue(), ^{
  387. // [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
  388. // });
  389. // }
  390. //}
  391. //- (void)showBackgroundTaskInactive {
  392. // //FLOG(@" called");
  393. // _job_counter--;
  394. // if (_job_counter < 0) _job_counter = 0;
  395. // //FLOG(@" _job_counter is %d", _job_counter);
  396. //
  397. // if (_job_counter == 0) {
  398. // if ([NSThread isMainThread]) {
  399. // [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
  400. // } else {
  401. // dispatch_async(dispatch_get_main_queue(), ^{
  402. // [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
  403. // });
  404. // }
  405. // }
  406. //}
  407.  
  408.  
  409. #pragma mark - managedObjectModel
  410. // Returns the managed object model for the application.
  411. // If the model doesn't already exist, it is created from the application's model.
  412. - (NSManagedObjectModel *)managedObjectModel {
  413.  
  414. if (_managedObjectModel != nil) {
  415. return _managedObjectModel;
  416. }
  417. else {
  418. NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"salonbook" ofType:@"momd"];
  419. NSURL *modelURL = [NSURL fileURLWithPath: modelPath];
  420. _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL: modelURL];
  421. return _managedObjectModel;
  422.  
  423. }
  424.  
  425. }
  426.  
  427. //
  428. //#pragma mark - postStoreChangeNotification
  429. //- (void)postStoreChangedNotification {
  430. //
  431. // dispatch_async(dispatch_get_main_queue(), ^{
  432. // [[NSNotificationCenter defaultCenter] postNotificationName: OSStoreChangeNotification
  433. // object:self];
  434. // });
  435. //}
  436.  
  437. @end
Advertisement
Add Comment
Please, Sign In to add comment