【问题标题】:NSManagedObjectContext in ios 10 and ios 9 (core data)ios 10 和 ios 9 中的 NSManagedObjectContext(核心数据)
【发布时间】:2017-07-12 12:33:53
【问题描述】:

我有一个使用支持 ios 9 和 ios 10 的核心数据的应用程序。我正在使用 xcode 8.2.1 来开发这个项目。 AppDelegate 文件具有在应用程序在 ios 10 上运行时获取 ManagedObjectContext 的方法,但是,当应用程序在 ios 9 上运行时我如何获取它。我尝试谷歌搜索但没有什么帮助。任何帮助!

我用来获取 ManagedObjectContext 的代码在这里:

 NSManagedObjectContext *context = ((AppDelegate*)[[UIApplication sharedApplication] delegate]).persistentContainer.viewContext;

【问题讨论】:

    标签: objective-c core-data ios9 ios10


    【解决方案1】:

    如果您的应用同时支持 ios 9 和 ios 10,那么您可以使用 #available 属性来检查当前运行的版本并相应地运行代码,因为 NSPersistentContainer 仅适用于 iOS 10 及更高版本。

    在 Swift 3 中

    // MARK: - Core Data Saving support
    
        func saveContext () {
    
            let coreDataFileName = "Use your core data file name"
    
            if #available(iOS 10.0, *) {
                let context = persistentContainer.viewContext
                if context.hasChanges {
                    do {
                        try context.save()
                    } catch {
                        // Replace this implementation with code to handle the error appropriately.
                        // fatalError() 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.
                        let nserror = error as NSError
                        fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
                    }
                }
            }else {
    
                if managedObjectContext.hasChanges {
                    do {
                        try managedObjectContext.save()
                    } catch let error as NSError {
                        print("Ops there was an error \(error.localizedDescription)")
                        abort()
                    }
                }
    
            }
        }
    
        // Applications default directory address
        lazy var applicationDocumentsDirectory: NSURL = {
            let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
            return urls[urls.count-1] as NSURL
        }()
        lazy var managedObjectModel: NSManagedObjectModel = {
            // 1
            let modelURL = Bundle.main.url(forResource: coreDataFileName, withExtension: "momd")!
            return NSManagedObjectModel(contentsOf: modelURL)!
        }()
        lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
            let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
            let url = self.applicationDocumentsDirectory.appendingPathComponent("\(coreDataFileName).sqlite")
            do {
                // If your looking for any kind of migration then here is the time to pass it to the options
                try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: nil)
            } catch let  error as NSError {
                print("Ops there was an error \(error.localizedDescription)")
                abort()
            }
            return coordinator
        }()
    
        lazy var managedObjectContext: NSManagedObjectContext = {
            //    // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the
            //    application.) This property is optional since there are legitimate error conditions that could cause the creation of the context to
            //    fail.
            let coordinator = self.persistentStoreCoordinator
            var context = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
            context.persistentStoreCoordinator = coordinator
            return context
        }()
    

    在目标中 - C 在 AppDelegate.m 中

    #pragma mark - Core Data Saving support
    
    @synthesize managedObjectContext = _managedObjectContext;
    @synthesize managedObjectModel = _managedObjectModel;
    @synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
    @synthesize persistentContainer = _persistentContainer;
    
    - (NSURL *)applicationDocumentsDirectory {
        // The directory the application uses to store the Core Data store file. This code uses a directory named "Your Bundle Indentifier" in the application's documents directory.
        return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
    }
    
    - (NSManagedObjectModel *)managedObjectModel {
        // The managed object model for the application. It is a fatal error for the application not to be able to find and load its model.
        if (_managedObjectModel != nil) {
            return _managedObjectModel;
        }
        NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Use your core data file name" withExtension:@"momd"];
        _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
        return _managedObjectModel;
    }
    
    - (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
        // The persistent store coordinator for the application. This implementation creates and returns a coordinator, having added the store for the application to it.
        if (_persistentStoreCoordinator != nil) {
            return _persistentStoreCoordinator;
        }
    
        // Create the coordinator and store
    
        _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
        NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Use your core data file name.sqlite"];
        NSError *error = nil;
        NSString *failureReason = @"There was an error creating or loading the application's saved data.";
        if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
            // Report any error we got.
            NSMutableDictionary *dict = [NSMutableDictionary dictionary];
            dict[NSLocalizedDescriptionKey] = @"Failed to initialize the application's saved data";
            dict[NSLocalizedFailureReasonErrorKey] = failureReason;
            dict[NSUnderlyingErrorKey] = error;
            error = [NSError errorWithDomain:@"YOUR_ERROR_DOMAIN" code:9999 userInfo:dict];
            // Replace this with code to handle the error appropriately.
            // 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.
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        }
    
        return _persistentStoreCoordinator;
    }
    
    
    - (NSManagedObjectContext *)managedObjectContext {
        // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.)
        if (_managedObjectContext != nil) {
            return _managedObjectContext;
        }
    
        NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
        if (!coordinator) {
            return nil;
        }
        _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
        [_managedObjectContext setPersistentStoreCoordinator:coordinator];
        return _managedObjectContext;
    }
    
    #pragma mark - Core Data Saving support
    
    - (void)saveContext {
    
        //Check current version.
        if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 10.0){
    
            NSManagedObjectContext *context =_persistentContainer.viewContext;
    
            if (context != nil) {
                NSError *error = nil;
                if ([context hasChanges] && ![context save:&error]) {
                    // Replace this implementation with code to handle the error appropriately.
                    // 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.
                    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
                    abort();
                }
            }
        }else{
            NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
            if (managedObjectContext != nil) {
                NSError *error = nil;
                if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
                    // Replace this implementation with code to handle the error appropriately.
                    // 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.
                    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
                    abort();
                }
            }
        }
    }
    

    在 AppDelegate.h 中使用

    #pragma mark - Core data for messages vriable
    @property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
    @property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
    @property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
    @property (readonly, strong) NSPersistentContainer *persistentContainer;
    
    - (void)saveContext;
    - (NSURL *)applicationDocumentsDirectory;
    

    【讨论】:

      【解决方案2】:

      正如 Jon Rose 所说,NSPersistentContainer 仅适用于 iOS 10。 如果您仍然需要您的应用程序在以前的版本中运行,最好的解决方案是使用旧的 Core Data Stack,这里有一篇很棒的博客解释了这两种方法之间的区别:Core Data in ios10

      另一种解决方案是在 swift 中使用#available 属性来执行核心数据堆栈或 NSPersistentContainer,这里有关于此的文档:Swift Attributes

      【讨论】:

      • 嘿@Lucas 我不熟悉 swift 任何链接,如果你有目标 c 中的此类教程?无论如何感谢您的帮助
      • 当然可以!这里有指向 Objective-C 中 #available 等效项的链接:stackoverflow.com/questions/7848766/…
      • 不幸的是,Objective-C 中没有 NSPersistentContainer 的教程,这里有文档,你能做的最好的就是快速按照教程进行操作,并尝试客观地复制它。 developer.apple.com/reference/coredata/…
      【解决方案3】:

      NSPersistentContainer 仅适用于 iOS 10 及更高版本。如果您需要支持较低的系统,那么您将无法使用它。您必须在没有NSPersistentContainer 的情况下设置自己的核心数据堆栈。

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-01-25
      • 2015-12-21
      • 2019-09-26
      • 1970-01-01
      • 2017-10-08
      • 1970-01-01
      • 1970-01-01
      • 2016-11-03
      相关资源
      最近更新 更多