2015-06-09 3 views
20

Ho appena scaricato la nuova beta Xcode 7.0 e ho effettuato una migrazione da Swift 1.2 a Swift 2. La migrazione apparentemente non ha modificato l'intero codice, in effetti un metodo saveContext() che era bene fino getta 2 errori per la linea:Migrazione Swift 2 saveContext() in appDelegate

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

operatore binario '& &' non può essere applicato a due operandi Bool

e

chiamata può buttare, ma non è contrassegnata con 'provare' e l'errore non viene gestito

Il metodo è simile al seguente:

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

Tutte le idee su come ottenerlo lavoro?

risposta

33

Il primo dei due errori che hai fornito è fuorviante, ma il secondo è azzeccato. Il problema è in !moc.save() che a partire da Swift 2, non restituisce più Bool ed è invece annotato throws. Ciò significa che devi utilizzare il metodo try e catch eventuali eccezioni che può emettere, invece di controllare solo se il suo valore restituito è vero o falso.

Per riflettere questo, un nuovo progetto creato in Xcode 7 utilizzando Core Data produrrà il seguente codice boilerplate che può sostituire il codice che si sta utilizzando.

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

Grazie che è la risposta giusta, Inoltre, è necessario aggiungere un '' dopo managedObjectContext così la linea si presenta come:!!! 'Se managedObjectContext .hasChanges {' e 'provare managedObjectContext .save()' – kalafun

+0

@kalafun No, in Xcode 7 il managedObjectContext non è opzionale. Postare aggiornamento sulla mia risposta – Ian

+0

Questo è strano sto usando xcode 7 beta e ha generato un errore a causa del punto esclamativo mancante. Aspettando il tuo aggiornamento .. – kalafun

9

La risposta da 0x7fffffff è corretto, ma di migliorare il codice standard di Apple, si può prendere l'errore specifico nel blocco di cattura utilizzando catch let error as NSError in questo modo:

func saveContext() { 
    if managedObjectContext.hasChanges { 
     do { 
      try managedObjectContext.save() 
     } catch let error as NSError { 

      NSLog("Unresolved error \(error), \(error.userInfo)") 
      // Handle Error 
     } 
    } 
} 

La pratica migliore è quella di utilizzare la strega var error sarà ancora disponibile se si utilizza in questo modo:

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

Allo stesso modo, se si è certi che managedObjectContext.save() volontà non throw un exception, il codice viene snellita a:

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

E per estrapolare sul perché managedObjectContext non è opzionale nel codice Swift 2, è perché il NSManagedObject(concurrencyType:) è un inizializzatore che non fallisce. In Xcode 6, il codice boilerplate ha restituito un contesto opzionale se lo NSPersistentStoreCoordinator è nullo, ma è possibile gestirlo facilmente controllando.

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