the programming lenguaje language documentacion swift swift2

programming - Swift 2 migration saveContext() en la aplicaciónDelegate



swift lenguaje (2)

Acabo de descargar la nueva versión beta de Xcode 7.0 e hice una migración de Swift 1.2 a Swift 2. Aparentemente, la migración no cambió todo el código, de hecho un método saveContext () que estuvo bien hasta que arrojó 2 errores para la línea:

if moc.hasChanges && !moc.save() {

El operador binario ''&&'' no se puede aplicar a dos operandos Bool

y

La llamada puede lanzar, pero no está marcada con ''probar'' y el error no se maneja

El método se ve así:

// MARK: - Core Data Saving support func saveContext () { if let moc = self.managedObjectContext { var error: NSError? = nil if moc.hasChanges && !moc.save() { // 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() } } }

¿Alguna idea sobre cómo hacerlo funcionar?


El primero de los dos errores que proporcionó es engañoso, pero el segundo es acertado. El problema está en !moc.save() que a partir de Swift 2, ya no devuelve Bool y en su lugar es throws anotados. Esto significa que debe try este método y catch las excepciones que pueda emitir, en lugar de simplemente verificar si su valor de retorno es verdadero o falso.

Para reflejar esto, un nuevo proyecto creado en Xcode 7 utilizando Core Data producirá el siguiente código repetitivo que puede reemplazar el código que está usando.

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() } } }


La respuesta por 0x7fffffff es correcta, pero para mejorar el código repetitivo de Apple, puedes detectar el error específico en el bloque catch let error as NSError usando el catch let error as NSError así:

func saveContext () { if managedObjectContext.hasChanges { do { try managedObjectContext.save() } catch let error as NSError { NSLog("Unresolved error /(error), /(error.userInfo)") // Handle Error } } }

La mejor práctica es utilizar el error var que seguirá estando disponible si solo lo usa de esta manera:

func saveContext () { if managedObjectContext.hasChanges { do { try managedObjectContext.save() } catch { NSLog("Unresolved error /(error), /(error.userInfo)") // Handle Error } } }

De la misma manera, si está seguro de que managedObjectContext.save() no generará una exception , el código se reducirá a:

func saveContext () { if managedObjectContext.hasChanges { try! managedObjectContext.save() } }

Y para extrapolar sobre por qué managedObjectContext no es opcional en el código de Swift 2, es porque NSManagedObject(concurrencyType:) es un inicializador que no falla. En Xcode 6, el código repetitivo devolvió un contexto opcional si NSPersistentStoreCoordinator es nulo, pero puede controlarlo fácilmente marcando.

lazy var managedObjectContext: NSManagedObjectContext = { let coordinator = self.persistentStoreCoordinator var moc = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType) moc.persistentStoreCoordinator = coordinator return moc }()