Reputation: 583
the Idea is to fetch "Typed" data using Coredata.
Updated
class func retrieve<T: AnyObject>(entityName:T.Type, sortBy:String? = nil, isAscending:Bool? = true, predicate:NSPredicate? = nil) -> AnyObject[] {
println("\(entityName)")
let request = NSFetchRequest(entityName: "Users")
request.returnsObjectsAsFaults = false
if predicate != nil {
request.predicate = predicate
}
if (sortBy != nil){
var sorter: NSSortDescriptor = NSSortDescriptor(key: sortBy , ascending: isAscending!)
request.sortDescriptors = [sorter]
}
var error: NSError? = nil
var fetchedResult = myDataModel.managedObjectContext.executeFetchRequest(request, error: &error)
if !error {
println("errore: \(error)")
}
println("retrieved \(fetchedResult.count) elements for \(entityName)")
return fetchedResult
}
now, what I wrote above is syntactically correct but I believe that there is also another way to make the same, maybe more 'easily'. I think the propose is clear :) I was trying to get Class name from entityName input param
an to call this function in the way below or something similar :
var xx = myDataModel.retrieve(Users.self)
where
Users: NSManagedeObject
do you have any suggestion?
Upvotes: 2
Views: 3116
Reputation: 11
This useful generic method
lazy var persistentContainer: NSPersistentContainer = {
let persistent = NSPersistentContainer(name: "SuperModelName")
persistent.loadPersistentStores { _, error in
print(error?.localizedDescription ?? "")
}
return persistent
}()
var moc: NSManagedObjectContext {
persistentContainer.viewContext
}
func fetch<T: NSManagedObject>(_ type: T.Type) -> [T] {
do {
let fetchRequest = NSFetchRequest<T>(entityName: type.description())
let fetchItem = try moc.fetch(fetchRequest)
return fetchItem
} catch {
print(error.localizedDescription)
return []
}
}
var beverageData: [Beverage] {
fetch(Beverage.self)
}
Upvotes: 0
Reputation: 1040
I couldn't seem to get the @objc
annotations to work for me, so instead I used:
let fetchRequest = NSFetchRequest(entityName: NSStringFromClass(entityClass).componentsSeparatedByString(".").last!)
which drills down to the entity name.
Upvotes: 0
Reputation: 22236
If, as @David pointed out, you add @objc(ModelClassName)
to your Model classes, here's a simplified version:
func retrieve<T: NSManagedObject>(entityClass:T.Type, sortBy:String? = nil, isAscending:Bool = true, predicate:NSPredicate? = nil) -> T[] {
let entityName = NSStringFromClass(entityClass)
let request = NSFetchRequest(entityName: entityName)
request.returnsObjectsAsFaults = false
request.predicate = predicate
if (sortBy != nil) {
var sorter = NSSortDescriptor(key:sortBy , ascending:isAscending)
request.sortDescriptors = [sorter]
}
var error: NSError? = nil
var fetchedResult = myDataModel.managedObjectContext.executeFetchRequest(request, error: &error)
if !error {
println("errore: \(error)")
}
println("retrieved \(fetchedResult.count) elements for \(entityName)")
return fetchedResult
}
One would use it this way:
@objc(Client)
class Client : NSManagedObject {
...
}
retrieve(Client) // This would get all clients in the database.
Upvotes: 3
Reputation: 41226
You can use NSStringFromClass
as long as you make sure that your model classes have non-mangled names by using @objc(ModelClassName)
let request = NSFetchRequest(entityName:NSStringFromClass(entityClass))
Another option, which is more work for you might be something like:
protocol EntityWithName {
class func entityName() -> String
}
extension MyModelObject : EntityWithName {
class func entityName() -> String {
return "MyModelObject"
}
}
extension NSManagedObjectContext {
// Create an instance of T and insert it into the Context (this is normal)
func insert<T:NSManagedObject where T:EntityWithName>(entityClass:T.Type) -> T? {
let entityDescription = NSEntityDescription.entityForName(entityClass.entityName(), inManagedObjectContext: self)
if !entityDescription {
return nil
}
return NSManagedObject(entity: entityDescription, insertIntoManagedObjectContext: self) as? T
}
}
let myModelObject = myContext.insert(MyModelObject.Self)
However, since your model objects are required to have NSManagedObject
as a superclass, trying to avoid "binding to objective-c" is really kind of pointless.
One other observation, if you're using mogenerator with it's new swift generation options, then the EntityWithName approach becomes much easier, you can just add:
extension MyModelObject : EntityWithName {}
To each of your user modifiable class files (not the _ one) and it should be fine since mogenerator generates an entityName class method.
Upvotes: 2