Search code examples
core-datansarrayswiftnsmanagedobjectcontextios8

Core Data in Swift


Trying to work with Core Data in Swift. Found this one example:

http://www.sep.com/sep-blog/2014/06/23/a-c-developer-learns-swift-part-1-core-data/

Created Entity "Person" with two string fields - lastname and firstname. Created UITableViewController (MainTableViewController) to display records on the screen. Created UIViewController (DetailViewController) to add new records. Created my own class (AddrBook) for entity data.

Does not work display the records contained in the entity in main class - MainTableViewController.

My class AddrBook.swift:

import UIKit
import CoreData

@objc(AddrBook)
class AddrBook: NSManagedObject {

@NSManaged var lastname:String
@NSManaged var firstname:String
}

UIViewController to add new records. DetailViewController.swift:

import UIKit
import CoreData

class DetailViewController: UIViewController {

@IBOutlet var lastNameField : UITextField = nil
@IBOutlet var firstNameField : UITextField = nil

init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}

init(coder aDecoder: NSCoder!) {
    super.init(coder: aDecoder)
}

override func viewDidLoad() {
    super.viewDidLoad()
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}

@IBAction func saveButtonPressed(sender : AnyObject) {

    let appDelegate:AppDelegate = (UIApplication.sharedApplication().delegate as AppDelegate)
    let context:NSManagedObjectContext = appDelegate.managedObjectContext
    let projectEntity = NSEntityDescription.entityForName("Person", inManagedObjectContext: context)
    var newPerson = AddrBook(entity: projectEntity, insertIntoManagedObjectContext: context)
    newPerson.lastname = lastNameField.text
    newPerson.firstname = firstNameField.text
    context.save(nil)
    self.dismissViewControllerAnimated(true, completion: nil)
}
}

Theoretically, in this class all goes well. Entry must be added.

The main class MainTableViewController.swift. To display the records. Trying to get them through the NSLog:

import UIKit
import CoreData

class MainTableViewController: UITableViewController {

init(style: UITableViewStyle) {
    super.init(style: style)
}

init(coder aDecoder: NSCoder!) {
    super.init(coder: aDecoder)
}

override func viewDidLoad() {
    super.viewDidLoad()

    let request = NSFetchRequest(entityName: "Person")
    request.returnsObjectsAsFaults = false
    let appDelegate:AppDelegate = (UIApplication.sharedApplication().delegate as AppDelegate)
    let context:NSManagedObjectContext = appDelegate.managedObjectContext
    var results:NSArray = context.executeFetchRequest(request, error: nil)
    for currentPerson in results as AddrBook[] {
        NSLog("\(currentPerson.lastname)")
        NSLog("\(currentPerson.firstname)")
    }
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}

override func numberOfSectionsInTableView(tableView: UITableView?) -> Int {
    return 1
}

override func tableView(tableView: UITableView?, numberOfRowsInSection section: Int) -> Int {
    return 0
}
}

Shows that there is an error in the expression

for currentPerson in results as AddrBook[] {

Error:

Cannot convert the expression's type 'AddrBook[]' to type 'AddrBook[]'

What am I doing wrong?


for LombaX:

override func viewDidLoad() {
    super.viewDidLoad()

    let request = NSFetchRequest(entityName: "Person")
    request.returnsObjectsAsFaults = false
    let appDelegate:AppDelegate = (UIApplication.sharedApplication().delegate as AppDelegate)
    let context:NSManagedObjectContext = appDelegate.managedObjectContext
    var results : AddrBook[]? = context.executeFetchRequest(request, error: nil) as? AddrBook[]
    NSLog("\(results)")
    if let array = results   // check for nil and unwrap
    {
        for currentPerson in array as AddrBook[] {
            NSLog("\(currentPerson.lastname)")
            NSLog("\(currentPerson.firstname)")
        }
    }

    // var results:NSArray = context.executeFetchRequest(request, error: nil)
    /*for currentPerson in results as AddrBook[] {
        NSLog("\(currentPerson.lastname)")
        NSLog("\(currentPerson.firstname)")
    }*/

}

Output NSLog - 2014-06-24 21:25:41.243 lesson-12-swift[1651:136375] nil

Variable results is nil :-(

Link to project in Dropbox: https://www.dropbox.com/s/q42rw5fw470timi/lesson-12-swift.zip


Solution

  • First, check that you filled the class in the data model: As ProjectName.AddrBook (for swift classes you have to specify even the project name). (NOTE: this is needed only if you haven't used the prefix @objc(AddrBook) before the class, but I see that you used it, so this is not the problem).

    or

    as AddrBook as in this image in the Class section, top right

    Data Model

    Moreover, change your cast like these:

    // since executeFetchRequest can return nil, cast it as an optional array of [AddrBook]
    // note: the first [AddrBook]? Can be omitted
    var results : [AddrBook]? = context.executeFetchRequest(request, error: nil) as? [AddrBook]  
    
    if let array = results   // check for nil and unwrap
    {
        for currentPerson in array as [AddrBook] {
            // print
        }
    }
    

    Or, less explicit and no check for nil

    var results = context.executeFetchRequest(request, error: nil)  
    
        for currentPerson in results as [AddrBook] {
            // print
        }