4

I am trying to follow this tutorial in order to save the Local Cache of UIWebView in my app.

I had to convert a few lines to swift 2 but i cannot find the way to solve the issue when add to NSManagedObjectContext save an argument of type NSError.

from the picture you can understand better what I mean.

enter image description here

How could I fix this? The code I'm using is:

func saveCachedResponse () {
    print("Saving cached response")

    // 1
    let delegate = UIApplication.sharedApplication().delegate as! AppDelegate
    let context = delegate.managedObjectContext!

    // 2
    let cachedResponse = NSEntityDescription.insertNewObjectForEntityForName("CachedURLResponse", inManagedObjectContext: context) as NSManagedObject

    cachedResponse.setValue(self.mutableData, forKey: "data")
    cachedResponse.setValue(self.request.URL!.absoluteString, forKey: "url")
    cachedResponse.setValue(NSDate(), forKey: "timestamp")
    cachedResponse.setValue(self.response.MIMEType, forKey: "mimeType")
    cachedResponse.setValue(self.response.textEncodingName, forKey: "encoding")

    // 3
    var error: NSError?
    let success = context.save(&error)
    if !success {
        print("Could not cache the response")
    }
}
SNos
  • 3,430
  • 5
  • 42
  • 92

4 Answers4

4

Surface Error

Handle print("Could not cache the response") not listed in the other answers:

do {
    try context.save()
} catch let error {
    print("Could not cache the response \(error)")
}

Avoid DB corruption, use perform block for all MOC access

As I like code examples to be somewhat robust, here is a more exhaustive solution:

func saveCachedResponse (context: NSManagedObjectContext) {
    context.performBlockAndWait({ () -> Void in

        let cachedResponse = NSEntityDescription.insertNewObjectForEntityForName("CachedURLResponse", inManagedObjectContext: context) as NSManagedObject
        cachedResponse.setValue(self.mutableData, forKey: "data")
        // etc.

        do {
            try context.save()
        } catch let error {
            print("Could not cache the response \(error)")
        }
    })
}
SwiftArchitect
  • 47,376
  • 28
  • 140
  • 179
  • how do you rethrow the error to the caller of saveCachedResponse? I get "invalid conversion from throwing to non-throwing" on the save() line. – user965972 Dec 03 '15 at 11:53
  • While I could answer this here, comments are not to ask question. Please see http://stackoverflow.com/questions/30826560/swift-2-invalid-conversion-from-throwing-function-of-type-to-non-throwing-funct, and http://stackoverflow.com/questions/31443645/simplest-way-to-throw-an-error-exception-with-a-custom-message-in-swift-2. – SwiftArchitect Dec 03 '15 at 23:21
3

In Swift 2.0

To save context, you have to use do { try ...} and catch {...} your error.

// Save the context.
    do {
        try context.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.
        //print("Unresolved error \(error), \(error.userInfo)")
    }

Edit

let entity = NSEntityDescription.entityForName("CachedURLResponse", inManagedObjectContext: context)
let newCacheUrl = NSEntityDescription.insertNewObjectForEntityForName(entity.name!, inManagedObjectContext: context)

newCacheUrl.setValue(NSDate(), forKey: "timeStamp")

I use something like this with Xcode 7 and I have not fatal error.

Antonio
  • 135
  • 1
  • 12
  • Thanks Antonio, I have changed to do { try ...} however, I get the error: fatal error: unexpectedly found nil while unwrapping an Optional value – SNos Jul 26 '15 at 16:53
  • **Try :** let context: NSManagedObjectContext = delegate.managedObjectContext – Antonio Jul 26 '15 at 18:26
  • Thank you Antonio, still have the same issue.. However, I solved it to compile my project with Xcode 6.4... Seems that Xcode 7 beta is not ready yet – SNos Jul 26 '15 at 21:34
  • I post an edit in my answer to try to solve your error. – Antonio Jul 27 '15 at 16:29
2
do {
    try managedObjectContext.save()
} catch let error as NSError
{
    NSLog("Unresolved error \(error), \(error.userInfo)")
}
Thomas Bormans
  • 5,156
  • 6
  • 34
  • 51
1
do {
    let success = try context.save()
} catch {

}

will do the trick. The error got nothing to do Xcode 7.

aaa
  • 1,649
  • 1
  • 16
  • 22