ioscore-datansfetchrequestswift3xcode8-beta2

How do I make a fetch request using NSManagedObject's new fetchRequest function?


In iOS 10 the CoreData team added a new "fetchRequest" method to NSManagedObject. It looks like this:

public class func fetchRequest() -> NSFetchRequest<NSFetchRequestResult>

Which, from what I understand, allows us to replace this:

let request = NSFetchRequest<MyEntity>(entityName: "MyEntity")

with this:

let request = MyEntity.fetchRequest()

However, when I try to make a simple request like this:

let request = MyEntity.fetchRequest()
do {
    results = try request.execute()
} catch let error {
    print("failed to fetch coffee object: \(error)")
}

I receive the following error:

Error Domain=NSCocoaErrorDomain Code=134060 "(null)" UserInfo={message=Cannot fetch without an NSManagedObjectContext in scope}

So, clearly the error is stating that I need to bring an NSManagedObjectContext into scope. I've been looking for examples but can seem to find a full example of how to perform a request using the new API features.

Question

Using the latest Core Data API features, how do I make a simple fetch request? The underlying question is how do I bring my NSmanagedObjectCotnext into scope.

I should note that I am able to successfully make a request using the traditional syntax.


Solution

  • Ok, I figured out two ways of doing this. The first approach, which is similar to my example code is just simply:

    var moc: NSManagedObjectContext!
    let request = MyEntity.fetchRequest()
    var results : [MyEntity]
    
     do {
         results = try moc.fetch(request)
     } catch { // error stuff}
    

    The second approach, which was shown in WWDC 2016 uses a function named "execute" on our fetch request object.

    If you view the details on NSFetchRequest you'll see a comment that clearly states that the operation must be performed with in a block.

       // Executes the fetch request using the current managed object context. This method must be called from within a block submitted to a managed object context.
        @available(iOS 10.0, *)
        public func execute() throws -> [ResultType]
    

    It's dawned on me that this was the way to perform the fetch:

    var moc: NSManagedObjectContext!
    let request = MyEntity.fetchRequest()
    var results : [MyEntity]
    
    moc.perform {
        self.results = try! request.execute()
    }
    

    For those who roll their own

    If you are rolling your own code you may find that your code does not compile. Included in the auto-generated code is a new method called fetchRequest that the compiler uses to pass the type along. Here's what the code looks like.

    @nonobjc public class func fetchRequest() -> NSFetchRequest<MyEntity> {
        return NSFetchRequest<MyEntity>(entityName: "MyEntity");
    }