Migration shift 2 saveContext () in appDelegate

I just downloaded the new beta version of Xcode 7.0 and made the transition from Swift 1.2 to Swift 2. The migration did not seem to change the whole code, in fact the saveContext () method, which was fine until it threw 2 errors for strings

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

The binary operator && cannot be applied to two Bool operands

and

A call may cause, but it is not marked with a "try", and the error is not processed.

The method is as follows:

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

Any ideas on how to make it work?

+20
swift swift2
Jun 09 '15 at 10:06
source share
2 answers

The first of the two errors you indicated is misleading, and the second is in place. The problem is !moc.save() , which with Swift 2 no longer returns Bool and throws annotated instead. This means that you should try use this method and catch any exceptions that it may throw, instead of just checking that its return value is true or false.

To reflect this, a new project created in Xcode 7 using Core Data will create the following boilerplate code that can replace the code you are using.

 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() } } } 
+33
Jun 09 '15 at 13:24
source share

The answer to 0x7fffffff is correct, but to improve the Apple pattern code, you can catch a specific error in the catch block with catch let error as NSError as follows:

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

The best practice is to use var error , the witch will still be available if you just use it like this:

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

In the same way, if you are sure that managedObjectContext.save() will not throw a exception , the code will be reduced to:

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

And to extrapolate to why managedObjectContext is not optional in Swift 2 code, this is because NSManagedObject(concurrencyType:) is an initializer that does not interrupt. In Xcode 6, the template code returned an optional context if NSPersistentStoreCoordinator is zero, but you can easily handle this by checking.

 lazy var managedObjectContext: NSManagedObjectContext = { let coordinator = self.persistentStoreCoordinator var moc = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType) moc.persistentStoreCoordinator = coordinator return moc }() 
+9
Jun 09 '15 at 2:48
source share



All Articles