Updating Items

With the persistent container set up, you can now interact with Core Data. Primarily, you will do this through its viewContext. This is how you will both create new entities and save changes.

The viewContext is an instance of NSManagedObjectContext. This is the portal through which you interact with your entities. You can think of the managed object context as an intelligent scratch pad. When you ask the context to fetch some entities, the context will work with its persistent store coordinator to bring temporary copies of the entities and object graph into memory. Unless you ask the context to save its changes, the persisted data remains the same.

Inserting into the context

When an entity is created, it should be inserted into a managed object context.

Open FlickrAPI.swift and import CoreData.

import Foundation
import CoreData

Next, update the photo(fromJSON:) method to take in an additional argument of type NSManagedObjectContext and use this context to insert new Photo instances.

private static func photo(fromJSON json: [String : Any],
                          into context: NSManagedObjectContext) -> Photo? {
    guard
        let photoID = json["id"] as? String,
        let title = json["title"] as? String,
        let dateString = json["datetaken"] as? String,
        let photoURLString = json["url_h"] as? String,
        let url = URL(string: photoURLString),
        let dateTaken = dateFormatter.date(from: dateString) else {

            // Don't have enough information to construct a Photo
            return nil
    }

    return Photo(title: title, photoID: photoID, remoteURL: url, dateTaken: dateTaken)

    var photo: Photo!
    context.performAndWait {
        photo = Photo(context: context)
        photo.title = title
        photo.photoID = photoID
        photo.remoteURL = url as NSURL
        photo.dateTaken = dateTaken as NSDate
    }

    return photo
}

Each NSManagedObjectContext is associated with a specific concurrency queue, and the viewContext is associated with the main, or UI, queue. You have to interact with a context on the queue that it is associated with. NSManagedObjectContext has two methods that ensure this happens: perform(_:) and performAndWait(_:). The difference between them is that perform(_:) is asynchronous and performAndWait(_:) is synchronous. Because you are returning the result of the insert operation from the photo(fromJSON:into:) method, you use the synchronous method.

The photo(fromJSON:into:) method is called from the method photos(fromJSON:). Update this method to take in a context and pass it to the photo(fromJSON:into:) method.

static func photos(fromJSON data: Data,
                   into context: NSManagedObjectContext) -> PhotosResult {
    do {
        ...
        var finalPhotos = [Photo]()
        for photoJSON in photosArray {
            if let photo = photo(fromJSON: photoJSON, into: context) {
                finalPhotos.append(photo)
            }
        }

Finally, you need to pass the viewContext to the FlickrAPI struct once the web service request successfully completes.

Open PhotoStore.swift and update processPhotosRequest(data:error:).

private func processPhotosRequest(data: Data?, error: Error?) -> PhotosResult {
    guard let jsonData = data else {
        return .failure(error!)
    }

    return FlickrAPI.photos(fromJSON: jsonData,
                            into: persistentContainer.viewContext)
}

Build and run the application now that all errors have been addressed. Although the behavior remains unchanged, the application is now backed by Core Data. In the next section, you will implement saving for both the photos and their associated image data.

Saving changes

Recall that NSManagedObject changes do not persist until you tell the context to save these changes.

Open PhotoStore.swift and update fetchInterestingPhotos(completion:) to save the changes to the context after Photo entities have been inserted into the context.

func fetchInterestingPhotos(completion: @escaping (PhotosResult) -> Void) {

    let url = FlickrAPI.interestingPhotosURL
    let request = URLRequest(url: url)
    let task = session.dataTask(with: request) {
        (data, response, error) -> Void in

        let var result = self.processPhotosRequest(data: data, error: error)

        if case .success = result {
            do {
                try self.persistentContainer.viewContext.save()
            } catch let error {
                result = .failure(error)
            }
        }

        OperationQueue.main.addOperation {
            completion(result)
        }
    }
    task.resume()
}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset