Jack Jack - 1 month ago 16
Swift Question

Crash when loading images from coreData

When I launch my app I download several photos from my server which are then saved to coreData like so (I followed this tutorial: Saving Picked Image to CoreData )

extension NewsFeedViewController {



func getContext() {
saveQueue.sync {


let appDelegate = UIApplication.shared.delegate as! AppDelegate
self.managedContext = appDelegate.persistentContainer.viewContext
}
}
}

extension NewsFeedViewController {

func prepareImageForSaving(image:UIImage) {

// use date as unique id
let date : Double = NSDate().timeIntervalSince1970

// dispatch with gcd.
convertQueue.async() {
print("dd")
// create NSData from UIImage
guard let imageData = UIImageJPEGRepresentation(image, 1) else {
// handle failed conversion
print("jpg error")
return
}


// scale image, I chose the size of the VC because it is easy


// send to save function
self.saveImage(imageData: imageData as NSData, date: date)

}
}
}

extension NewsFeedViewController {

func saveImage(imageData:NSData, date: Double) {


saveQueue.async(flags: .barrier) {

// create new objects in moc
guard let moc = self.managedContext else {

return
}

guard let fullRes = NSEntityDescription.insertNewObject(forEntityName: "Blogger", into: moc) as? FullRes else {
// handle failed new object in moc
print("moc error")
return
}

//set image data of fullres
fullRes.imageData = imageData as Data


// save the new objects
do {

try moc.save()

} catch {
fatalError("Failure to save context: \(error)")
}

// clear the moc
moc.refreshAllObjects()
}

}

}


extension NewsFeedViewController {

func loadImages(_ fetched:@escaping (_ images:[FullRes]?) -> Void) {

saveQueue.async() {
guard let moc = self.managedContext else {
return
}

let fetchRequest :NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "FullRes")
//let fetchRequest = NSFetchRequest(entityName: "FullRes")//NSFetchRequest(entityName: "FullRes")
print(fetchRequest)

do {

let results = try moc.fetch(fetchRequest)
let imageData = results as? [FullRes]
DispatchQueue.main.async() {
fetched(imageData)

}
} catch let error as NSError {
print("Could not fetch \(error), \(error.userInfo)")
return
}
}
}

}


In that code I am preparing the image to be saved - saving it, and then in other parts of my code(not posted here) and checking if there is a internet connection. If there isn't load the images, so I call the loadImages() function which I have posted above.

When calling it I get this error:

enter image description here

If anyone can help me with this, it's much appreciated!!

Answer

There is no problem in your code. I have implemented your exact code and it is working perfectly. You should now try to isolate your problem. Try to comment functions that are using the Internet like functions handling logged in users and downloading content in general.

Also check your AppDelegate for functions that might cause an early crash once your App starts without internet.

Always try to catch exceptions caused by missing reachability.

For that purpose I'm using the following function:

import Foundation
import SystemConfiguration

open class Reachability {

    class func isConnectedToNetwork() -> Bool {

        var zeroAddress = sockaddr_in()
        zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress))
        zeroAddress.sin_family = sa_family_t(AF_INET)

        guard let defaultRouteReachability = withUnsafePointer(to: &zeroAddress , {
            $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {zeroSockAddress in
                SCNetworkReachabilityCreateWithAddress(nil, zeroSockAddress)
            }
        }) else {
            return false
        }

        var flags : SCNetworkReachabilityFlags = []
        if !SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) {
            return false
        }

        let isReachable = flags.contains(.reachable)
        let needsConnection = flags.contains(.connectionRequired)
        return (isReachable && !needsConnection)
    }

} 

Called by:

if Reachability.isConnectedToNetwork() == true {
    //execute your code
} else {
    //catch print
}