I have a core-data entity with several attributes, and I want a list of all the objects in one attribute. My code looks like this:
let appDel:AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
let context:NSManagedObjectContext = appDel.managedObjectContext!
let sortDesc = NSSortDescriptor(key: "username", ascending: true)
let fetchReq = NSFetchRequest(entityName: "Identities")
fetchReq.sortDescriptors = [sortDesc]
fetchReq.valueForKey("username")
let en = NSEntityDescription.entityForName("Identities", inManagedObjectContext: context)
userList = context.executeFetchRequest(fetchReq, error: nil) as [Usernames]
But this gives me an NSException-error, and I can't figure out why, or how I'm supposed to do this. I've read the NSFetchRequest class description but couldn't make much sense out of it.
Any suggestions would be appreciated.
EDIT: After a tip from Bluehound I changed my code to this:
var userList = [Model]()
@IBAction func printUsers(sender: AnyObject) {
let appDel:AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
let context:NSManagedObjectContext = appDel.managedObjectContext!
let sortDesc = NSSortDescriptor(key: "friendID", ascending: true)
let fetchReq = NSFetchRequest(entityName: "Identities")
fetchReq.sortDescriptors = [sortDesc]
fetchReq.propertiesToFetch = ["friendID"]
let en = NSEntityDescription.entityForName("Identities", inManagedObjectContext: context)
userList = context.executeFetchRequest(fetchReq, error: nil) as [Model]
println(userList)
}
The runtime error is gone but I still don't know if it works because I'm not sure how to convert the list to a list of strings.
As always, suggestions would be appreciated.
There are two possibilities: You can issue a normal fetch request
and extract an array containing the wanted attribute from the result,
using map()
:
let fetchReq = NSFetchRequest(entityName: "Identities")
fetchReq.sortDescriptors = [sortDesc]
var error : NSError?
if let result = context.executeFetchRequest(fetchReq, error: &error) as? [Model] {
let friendIDs = map(result) { $0.friendID }
println(friendIDs)
} else {
println("fetch failed: \(error!.localizedDescription)")
}
Swift 2:
let fetchReq = NSFetchRequest(entityName: "Identities")
fetchReq.sortDescriptors = [sortDesc]
do {
let result = try context.executeFetchRequest(fetchReq) as! [Model]
let friendIDs = result.map { $0.friendID }
print(friendIDs)
} catch let error as NSError {
print("fetch failed: \(error.localizedDescription)")
}
Or you set the resultType
to .DictionaryResultType
and propertiesToFetch
to the wanted attribute.
In this case the fetch request will return an array of dictionaries:
let fetchReq = NSFetchRequest(entityName: "Identities")
fetchReq.sortDescriptors = [sortDesc]
fetchReq.propertiesToFetch = ["friendID"]
fetchReq.resultType = .DictionaryResultType
var error : NSError?
if let result = context.executeFetchRequest(fetchReq, error: &error) as? [NSDictionary] {
let friendIDs = map(result) { $0["friendID"] as String }
println(friendIDs)
} else {
println("fetch failed: \(error!.localizedDescription)")
}
Swift 2:
let fetchReq = NSFetchRequest(entityName: "Identities")
fetchReq.sortDescriptors = [sortDesc]
fetchReq.propertiesToFetch = ["friendID"]
fetchReq.resultType = .DictionaryResultType
do {
let result = try context.executeFetchRequest(fetchReq) as! [NSDictionary]
let friendIDs = result.map { $0["friendID"] as! String }
print(friendIDs)
} catch let error as NSError {
print("fetch failed: \(error.localizedDescription)")
}
The second method has the advantage that only the specified properties are fetched from the database, not the entire managed objects.
It has the disadvantage that the result does not include pending
unsaved changes in the managed object context (includesPendingChanges:
is implicitly set to false
when using .DictionaryResultType
).