0

I would like to implement saving and fetching of core data directly in a class definition. But when i try to instance it i get the following error: "CoreData: error: Failed to call designated initialiser on NSManagedObject class 'User'". Can anyone tell me what i'm doing wrong? The entity has been created and the class is prefixed with the project name. It works when I have these functions in the ViewController, but am getting the error when i try to implement it in the class.

my code so far is:

import Foundation
import CoreData
import UIKit

@objc(User)
class User: NSManagedObject {

@NSManaged var name: String
@NSManaged var email: String

var users = [NSManagedObject]()

func saveUser(name: String, email: String) {
    //1
    let appDelegate =
    UIApplication.sharedApplication().delegate as AppDelegate

    let managedContext = appDelegate.managedObjectContext!

    //2
    let entity =  NSEntityDescription.entityForName("User",
        inManagedObjectContext:
        managedContext)

    let user = NSManagedObject(entity: entity!,
        insertIntoManagedObjectContext:managedContext)

    //3
    user.setValue(name, forKey: "name")
    user.setValue(email, forKey: "email")

    //4
    var error: NSError?
    if !managedContext.save(&error) {
        println("Could not save \(error), \(error?.userInfo)")
    }
    //5
    users.append(user)
}

func fetchUser() {
    //1
    let appDelegate =
    UIApplication.sharedApplication().delegate as AppDelegate

    let managedContext = appDelegate.managedObjectContext!

    //2
    let fetchRequest = NSFetchRequest(entityName:"User")

    //3
    var error: NSError?

    let fetchedResults =
    managedContext.executeFetchRequest(fetchRequest,
        error: &error) as? [NSManagedObject]

    if let results = fetchedResults {
        users = results
    } else {
        println("Could not fetch \(error), \(error!.userInfo)")
    }
}

func isValidEmail(testStr:String) -> Bool {
    let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}"
    if let emailTest = NSPredicate(format:"SELF MATCHES %@", emailRegEx) as NSPredicate? {
        return emailTest.evaluateWithObject(testStr)
    }
    return false
  }
}

instancing in ViewController:

var userInstance:User = User()
MarkoDeveloper
  • 287
  • 1
  • 3
  • 11
  • 1
    `var userInstance:User = User()` creates a user object without using the designated initializer. – Martin R Jun 08 '15 at 11:55
  • how do i initialize it then? Most of the examples i find are in Objective-C and i barely know Swift so could you please help? :) – MarkoDeveloper Jun 08 '15 at 11:56
  • You already do it correctly in the `fetchUser()` method: `let user = NSManagedObject(entity: entity!, insertIntoManagedObjectContext:managedContext)`. – Martin R Jun 08 '15 at 11:58
  • Then why am i getting the error? Can i make this class "static" like in C# so i don't have to instance it? – MarkoDeveloper Jun 08 '15 at 12:02
  • Calling `User()` *is* making an instance of it (or attempting to do so), and making the class equivalent to C#'s `static` class in Swift effectively means there are **no** initializers, and as such, you wouldn't be able to instantiate it with the `NSManagedObject()` approach. I mean, it just doesn't make sense. You could potentially make the function's `class` functions, if that makes sense for what you are doing. – nhgrif Jun 08 '15 at 12:06

1 Answers1

3

var userInstance:User = User() creates a user object without using the designated initializer, and that causes the error message.

If the only reason to create this User object is to call the saveUser() and fetchUser() methods then it is the wrong approach, and you should define the methods as class methods:

class func saveUser(name: String, email: String) { ... }

class func fetchUser() { ... }

which you then can call as

User.saveUser(...)
User.fetchUser()

But note that

var users = [NSManagedObject]()

should not be a property of the User class. It should be (for example) a property of your view controller, correctly typed as

var users = [User]()

and the fetchUser() method should return an array.

Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • That sounds right but i'm not an iOS Developer(obviously) so i don't know how to do that :/. Thank you for your time, but obviously i need to hit the docs. – MarkoDeveloper Jun 08 '15 at 12:39
  • I did exactly as you said and it partially works but I am still getting the following: "CoreData: warning: Unable to load class named 'AppName.User' for entity 'User'. Class not found, using default NSManagedObject instead." Anything you can add which would help me solve this? – MarkoDeveloper Jun 09 '15 at 10:29
  • @MarkoMiletić: See http://stackoverflow.com/questions/25076276/unable-to-find-specific-subclass-of-nsmanagedobject and its various answers. – Martin R Jun 09 '15 at 10:33
  • It worked when i removed the 'AppName' from the class name, don't know why exactly cause usually it needs to be there but it's ok now. :) Thank you again for all your help. – MarkoDeveloper Jun 09 '15 at 11:13