8

I've reviewed Apple's:

Xcode 8 Release notes:
https://developer.apple.com/library/content/releasenotes/DeveloperTools/RN-Xcode/Introduction.html

Migrating to Swift 2.3 or Swift 3 from Swift 2.2
https://swift.org/migration-guide/

What's New in Core Data in macOS 10.12, iOS 10.0, tvOS 10.0, and watchOS 3.0
https://developer.apple.com/library/content/releasenotes/General/WhatNewCoreData2016/ReleaseNotes.html#//apple_ref/doc/uid/TP40017342-CH1-DontLinkElementID_1

And many others... but the one document that should be available from Apple, the Core Data Programming Guide, hasn't been updated from Swift 2.
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreData/FetchingObjects.html#//apple_ref/doc/uid/TP40001075-CH6-SW1

Ideally I'm looking for something like this but for Swift 3.
https://www.raywenderlich.com/115695/getting-started-with-core-data-tutorial

Any leads would be very much appreciated.

Per Tom's comment (below) What step am I missing?

1) Create a new project "Test"

2) Select use CoreDate (This creates Test.xcdatamodeld)

This will auto populate AppDelegate with the following (default comments removed):

func applicationWillTerminate(_ application: UIApplication) {
self.saveContext()
}
lazy var persistentContainer: NSPersistentContainer = {
    let container = NSPersistentContainer(name: "Test")
    container.loadPersistentStores(completionHandler: { (storeDescription, error) in
        if let error = error as NSError? {
            fatalError("Unresolved error \(error), \(error.userInfo)")
        }
    })
    return container
}()
func saveContext () {
    let context = persistentContainer.viewContext
    if context.hasChanges {
        do {
            try context.save()
        } catch {
            let nserror = error as NSError
            fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
        }
    }
}

3) Create entity "Foo"

4) Add Attribute "bar" type String

5) Under ViewController.swift add the following (This was copied from Apple, I just replaced "...use" with "print")

func findAnimals() {
    let request: NSFetchRequest<Foo> = Foo.fetchRequest
    do {
        let searchResults = try context.fetch(request)
        print(searchResults)
    } catch {
        print("Error with request: \(error)")
    }
}

6) Add findAnimals() under override func viewDidLoad().

However this has errors specifically:

  1. NSFetchRequest < Use of undeclared type 'NSFetchRequest'
  2. context < Use of unresolved identifier 'context'

7) So you go back and add something this to the function under the viewController to make the container accessible (which wasn't in the example form Apple).

let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext

Great we cleared 1 of the 2 error but the error " Use of undeclared type 'NSFetchRequest' " remains.

And here is where I'm stuck. Even after reviewing all of Apple's published materials I am unable to find a complete example.

Michael Garito
  • 3,005
  • 1
  • 11
  • 11
  • What specifically do you not understand? – Tom Harrington Sep 20 '16 at 16:03
  • The limited documentation implies all one has to do is make an entity in the xcdatamodeld and it will will automatically be recognized. However I'm constantly receiving "unresolved identifier". – Michael Garito Sep 20 '16 at 20:36
  • 1
    Did you import CoreData? – shallowThought Oct 04 '16 at 14:46
  • you can get more about Swift3 core data and concurrency in lynda.com,the course "Core Data for iOS and macOS Enterprise Developers" by Jonathan Bott – Lydia Dec 12 '16 at 09:02
  • Here's some Apple documentation on how to get the context with dataController.managedObjectContext (if you separate the App delegate core data implementation into a DataController class). Use in views: https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreData/nsfetchedresultscontroller.html#//apple_ref/doc/uid/TP40001075-CH8-SW1 Separating into another class: https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreData/IntegratingCoreData.html#//apple_ref/doc/uid/TP40001075-CH9-SW1 – Efren Apr 27 '17 at 08:44

4 Answers4

7

@Aaron Thanks again for the video link, that got me on the right track. Below is quick walk through for the bare minimum needed to fetch, add, and clear from core data with Swift 3 in Xcode 8.

  1. New project > iOS Single view application
  2. Product Name: "Sample"
  3. Use Core Data (checked)
  4. Save
  5. Open Sample.xcdatamodeld
  6. Add and entity: "SampleEntity"
  7. Use the Data Model inspector to set Codegen (under Class) to "Class Definition"
  8. Create an attribute under the new entity: "sampleAttribute"
  9. Open ViewController.swift
  10. Under "import UIKit" add "import CoreData"
  11. Under Class ViewController add the following:

    let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
    
    // Get data from he attribute
    func getSample() {
        let request: NSFetchRequest = SampleEntity.fetchRequest()
        request.resultType = NSFetchRequestResultType.dictionaryResultType
        do {
            let searchResults = try context.fetch(request as! NSFetchRequest<NSFetchRequestResult>) as! [NSDictionary]
            let searchResultsArray = searchResults.map { $0["sampleAttribute"] as! String}
            print("searchResultsArray", searchResultsArray)
        } catch {
            print("Error with request: \(error)")
        }
    }
    
    // Save to the attribute
    func setSample() {
        let saveSample = SampleEntity(context: context)
        saveSample.sampleAttribute = "Save a new string."
        do {
            try context.save()
        } catch {
             print("Error with save: \(error)")
        }
    }
    
    // clear the attribute
    func resetSample() {
        let clearSample: NSFetchRequest = SampleEntity.fetchRequest()
        let deleteResults = NSBatchDeleteRequest(fetchRequest: clearSample as! NSFetchRequest<NSFetchRequestResult>)
        do {
            try context.execute(deleteResults)
            try context.save()
        } catch {
            print("Error with save: \(error)")
        }
    }
  12. Under override func viewDidLoad() add the following:

    getSample()
    setSample()
    getSample()
    resetSample()
    getSample()
  13. Run and you will see the following printed in the debugging area:

    searchResultsArray []                       // Initially the attribute is empty
    searchResultsArray ["Save new string."]     // The attribute now contains the string 
    searchResultsArray []                       // This attribute has been cleared
Michael Garito
  • 3,005
  • 1
  • 11
  • 11
2

May be the video of this years WWDC What's New in Core Data can give you some more inside.

At approximately minute 31:20 he is showing some code regarding NSFetchRequest.

Aaron
  • 413
  • 5
  • 13
  • Thanks for the link! I've watched the entire video and thing that caught my attention is that the demo uses the "mater-detail" template not the "single view" template. After comparing the two temples side by side I noticed that the single view template has the "Codegen" set to "Manual/None" instead of the new automatic "Class definition" setting. More to come! – Michael Garito Sep 22 '16 at 22:08
0

From my understanding, NSPersistentContainer decouples main context and worker context in a simple way. One can simply call container.viewContext for any UI level data access (old NSMainQueueConcurrencyType), and use container.newBackgroundContext for other data import work (old NSPrivtaeQueueConcurrencyType). And by setting automaticallyMergesChangesFromParent to true to any context, it equals to old listening to NSManagedObjectContextDidSaveNotification.

Reference: http://holko.pl/2016/06/23/core-data/

BabyPanda
  • 1,562
  • 12
  • 18
0

I still cannot leave comments. So let me put it here. I believe these two videos will help you a lot. Great Stanford Courses by Paul Hegarty are up to date!

https://www.youtube.com/watch?v=ssIpdu73p7A - lecture about CoreData https://www.youtube.com/watch?v=whF63GTaW1w - demo for using CoreData.

DJ-Glock
  • 1,277
  • 2
  • 12
  • 39
  • I actually got this working back in October of 2016. You can see what I did with core data by checking out my app MathFit on the AppStore. - https://itunes.apple.com/us/app/mathfit/id1173338351?mt=8 – Michael Garito May 13 '17 at 18:17