ios - programar - xcode 6
¿Cómo crear managedObjectContext usando Swift 3 en Xcode 8? (5)
Problema de enfrentamiento "El valor del tipo ''AppDelegate'' no tiene ningún miembro ''managedObjectContext'' en el nuevo Xcode 8 (usando Swift 3, iOS 10) al intentar crear un nuevo contexto en View Controller
let context = (UIApplication.shared().delegate as! AppDelegate).managedObjectContext
En Xcode 8 no hay código para managedObjectContext dentro del archivo AppDelegate.swift. El código de la pila de datos centrales dentro de AppDelegate.swift se presenta solo con: lazy var persistentContainer: propiedad NSPersistentContainer y func saveContext (). No existe la propiedad managedObjectContext.
¿Cómo crear managedObjectContext usando Swift 3 en Xcode 8) o tal vez no hay necesidad de hacerlo usando Swift 3?
En Swift3, puede acceder al managedObjectContext a través de viewContext como
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
Esta opción está disponible si los datos principales se habilitaron al crear el proyecto. Sin embargo, para el proyecto existente en el que desea incluir datos centrales, realice el proceso normal de agregar los datos centrales y agregue el siguiente código que le permitirá obtener el
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "you_model_file_name")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error {
fatalError("Unresolved error /(error), /(error.userInfo)")
}
})
return container
}()
Deberá importar CoreData.
Nota: Para Swift3, la subclase ManagedObject se genera automáticamente. Ver más de developer.apple.com/videos/play/wwdc2016/242
La solución de
lleva a la mayor parte del camino para iOS 10.0, pero no aborda iOS 9.0 o inferior, que no puede acceder a ese método y necesita construir manualmente el
NSManagedObjectModel
.
Aquí está la solución que funcionó para mí:
var context: NSManagedObjectContext?
if #available(iOS 10.0, *) {
context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
} else {
// iOS 9.0 and below - however you were previously handling it
guard let modelURL = Bundle.main.url(forResource: "Model", withExtension:"momd") else {
fatalError("Error loading model from bundle")
}
guard let mom = NSManagedObjectModel(contentsOf: modelURL) else {
fatalError("Error initializing mom from: /(modelURL)")
}
let psc = NSPersistentStoreCoordinator(managedObjectModel: mom)
context = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let docURL = urls[urls.endIndex-1]
let storeURL = docURL.appendingPathComponent("Model.sqlite")
do {
try psc.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: storeURL, options: nil)
} catch {
fatalError("Error migrating store: /(error)")
}
}
Está claro que el cambio a 10.0 hace que CoreData sea significativamente más simple, pero es lamentable que sea tan doloroso para los desarrolladores existentes dar el salto ...
Para implementar lo anterior, solo asegúrese de lanzar el Contenedor
persistentContainer
en su AppDelegate.swift, definido en la respuesta de
.
Movió todo el código de la pila de datos principales a un solo archivo y agregó iOS 10 e inferior a iOS10. a continuación es mi intento (no estoy seguro de que sea totalmente a la altura)
import Foundation
import CoreData
class CoreDataManager {
// MARK: - Core Data stack
static let sharedInstance = CoreDataManager()
private lazy var applicationDocumentsDirectory: URL = {
// The directory the application uses to store the Core Data store file. This code uses a directory named in the application''s documents Application Support directory.
let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
return urls[urls.count-1]
}()
private 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: "CoreDataSwift", withExtension: "momd")!
return NSManagedObjectModel(contentsOf: modelURL)!
}()
private 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("CoreDataSwift.sqlite")
var failureReason = "There was an error creating or loading the application''s saved data."
do {
// Configure automatic migration.
let options = [ NSMigratePersistentStoresAutomaticallyOption : true, NSInferMappingModelAutomaticallyOption : true ]
try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: options)
} 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 = {
var managedObjectContext: NSManagedObjectContext?
if #available(iOS 10.0, *){
managedObjectContext = self.persistentContainer.viewContext
}
else{
// 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
managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
managedObjectContext?.persistentStoreCoordinator = coordinator
}
return managedObjectContext!
}()
// iOS-10
@available(iOS 10.0, *)
lazy var persistentContainer: NSPersistentContainer = {
/*
The persistent container for the application. This implementation
creates and returns a container, having loaded 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.
*/
let container = NSPersistentContainer(name: "CoreDataSwift")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
// 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.
/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
fatalError("Unresolved error /(error), /(error.userInfo)")
}
})
print("/(self.applicationDocumentsDirectory)")
return container
}()
// 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()
}
}
}
}
Primero, obtenga el objeto AppDelegate: -
let appDelegateObject = UIApplication.shared.delegate as! AppDelegate
Y ahora, podemos obtener objetos gestionados como:
let managedObject = appDelegateObject.persistentContainer.viewContext
NSPersistentContainer
tiene una propiedad
viewContext
que es un tipo
NSManagedObjectContext
.
Como nota al margen, si crea una aplicación Master-Detail en Xcode 8, el código de muestra de Apple coloca la propiedad
managedObjectContext
en el archivo MasterViewController.swift y la establece utilizando dicha propiedad
viewContext
en AppDelegate.