同时使用iOS 9和iOS 10 CoreData

同时使用iOS 9和iOS 10 CoreData,ios,swift,xcode,core-data,Ios,Swift,Xcode,Core Data,我有一个关于与核心数据相关的Swift 3的问题。我正在用Xcode 8开发Swift应用程序,我需要支持iOS 9和iOS 10。问题是我不知道如何获取AppDelegate和用于存储和从实体获取数据的上下文。我认为我的代码应该是这样的: #if avaliable(iOS10,*) { // iOS 10 code } else { // iOS 9 code } var coreDataManager: CoreDataManagerProtocol! #if avai

我有一个关于与核心数据相关的Swift 3的问题。我正在用Xcode 8开发Swift应用程序,我需要支持iOS 9和iOS 10。问题是我不知道如何获取AppDelegate和用于存储和从实体获取数据的上下文。我认为我的代码应该是这样的:

#if avaliable(iOS10,*)
{
     // iOS 10 code
} else
{
    // iOS 9 code
}
var coreDataManager: CoreDataManagerProtocol!
#if available(iOS10,*)
{
    coreDataManager = CoreDataManagerNewStack()
} else
{
    coreDataManager = CoreDataManagerOldStack()
}
但我不知道该怎么办

有什么想法吗

希望您能为iOS 9和iOS 10的核心数据在Swift 3中提供一些更正帮助

由于您需要iOS 9和iOS 10的核心数据代码,因此不必使用iOS 9中不支持的NSPersistentContainer,因此必须使用旧方法

如果在项目创建时您尚未包含核心数据,并且以后希望包含核心数据,请执行以下步骤:-

第一步。转到构建阶段->将二进制文件链接到库->单击+符号->添加CoreData.framework

第二步。现在进入文件->新建文件->选择数据模型

第三步。现在,您需要在AppDelegate.swift中编写一些代码,以便设置:-

import UIKit
import CoreData

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch. 
        return true
    }

    func applicationWillResignActive(_ application: UIApplication) {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
    }

    func applicationDidEnterBackground(_ application: UIApplication) {
        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    }

    func applicationWillEnterForeground(_ application: UIApplication) {
        // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
    }

    func applicationDidBecomeActive(_ application: UIApplication) {
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }

    func applicationWillTerminate(_ application: UIApplication) {
        self.saveContext()

    }

    // MARK: - Core Data stack

    lazy var applicationDocumentsDirectory: NSURL = {
        // The directory the application uses to store the Core Data store file. This code uses a directory named "hacker.at.work.mTirgger" in the application's documents Application Support directory.
        let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
        return urls[urls.count-1] as NSURL
    }()

    lazy var managedObjectModel: NSManagedObjectModel = {
        // The managed object model for the application. This property is not optional. It is a fatal error for the application not to be able to find and load its model.
        let modelURL = Bundle.main.url(forResource: "Model", withExtension: "momd")!
        return NSManagedObjectModel(contentsOf: modelURL)!
    }()

    lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
        // The persistent store coordinator for the application. This implementation creates and returns a coordinator, having added the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail.
        // Create the coordinator and store
        let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
        let url = self.applicationDocumentsDirectory.appendingPathComponent("SingleViewCoreData.sqlite")
        var failureReason = "There was an error creating or loading the application's saved data."
        do {
            try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: nil)
        } catch {
            // Report any error we got.
            var dict = [String: AnyObject]()
            dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data" as AnyObject?
            dict[NSLocalizedFailureReasonErrorKey] = failureReason as AnyObject?

            dict[NSUnderlyingErrorKey] = error as NSError
            let wrappedError = NSError(domain: "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 \(wrappedError), \(wrappedError.userInfo)")
            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 managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
        managedObjectContext.persistentStoreCoordinator = coordinator
        return managedObjectContext
    }()

    // MARK: - Core Data Saving support

    func saveContext () {
        if managedObjectContext.hasChanges {
            do {
                try managedObjectContext.save()
            } catch {
                // 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.
                let nserror = error as NSError
                NSLog("Unresolved error \(nserror), \(nserror.userInfo)")
                abort()
            }
        }
    }
}

这就是您在Swift 3中为iOS 9和iOS 10准备的所有核心数据。享受

如果您想支持iOS9,那么最好不要使用任何新的iOS10内容

现在坚持使用ios9api,将来当您最终放弃iOS9支持时,您可以重构代码以使用更新的方法

编辑:为了清楚起见,所有iOS9代码都将在iOS10上正常运行。您不需要在那里做任何特殊的事情,它都是向后兼容的。

CoreData同时用于iOS9和iOS10

对于您可能需要它的人:

这是2016年5月最新发布的Xcode7 for iOS9中未经修改的主细节应用程序模板。我已经用最新的Xcode版本8.2.1对其进行了更新

使用此模板,您可以开发使用与iOS9和iOS10兼容的CoreData的应用程序,至少目前是2017年5月

AppDelegate.swift

MasterViewController.swift

数据模型是源于模板以及情节提要的原始模型。两者都没有修改。

您可以使用新的API,并通过执行以下操作从中获得好处:

#if avaliable(iOS10,*)
{
     // iOS 10 code
} else
{
    // iOS 9 code
}
var coreDataManager: CoreDataManagerProtocol!
#if available(iOS10,*)
{
    coreDataManager = CoreDataManagerNewStack()
} else
{
    coreDataManager = CoreDataManagerOldStack()
}
然后使用新堆栈将新CoreData实现到一个类中:

class CoreDataManagerNewStack: CoreDataManagerProtocol {
    var container: NSPersistentContainer
    // etc
}
和旧的一个与上面的代码粘贴与整个代码生成堆栈

class CoreDataManagerOldStack: CoreDataManagerProtocol {
     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 managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
        managedObjectContext.persistentStoreCoordinator = coordinator
        return managedObjectContext
    }()
    // etc
}

为什么你认为在iOS 9和iOS 10中获取AppDelegate和上下文必须以不同的方式处理?@Josep问自己iOS 9和iOS 10之间的核心数据行为是否不同。然后问问你自己你需要区分的确切原因。然后更新您的OP。例如,我有三个应用程序,它们跨越iOS 6到10.2,在核心数据实现方面没有差异。我再次下载了Xcode 7,这是9月的Xcode 8之前的最新版本。我基于主详细信息模板创建了一个新项目。我没有改变任何事情。我已使用Xcode 8.2.1打开项目,编辑器已对其进行了更新,并已开始给出我无法更正的错误。请为您的问题创建一个新问题,评论不是正确的提问位置。为什么不为iOS 10使用新的iOS 10堆栈,而为iOS 10使用新的iOS 10堆栈?一些项目还提供了iOS 9和10的兼容性
class CoreDataManagerOldStack: CoreDataManagerProtocol {
     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 managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
        managedObjectContext.persistentStoreCoordinator = coordinator
        return managedObjectContext
    }()
    // etc
}