Swift Core Data fetch data 1 column [duplicate] - swift

This question already has an answer here:
Fetching selected attribute in entities
(1 answer)
Closed 4 years ago.
I cannot fetch data by "name" column. When respone, system print all attribute in People. Help me, thanks.
private func getPeople(product: String) {
let temp = product
let entityDescription = NSEntityDescription.entity(forEntityName: "People", in: context)
let fetchRequest = NSFetchRequest<NSFetchRequestResult>()
fetchRequest.entity = entityDescription
fetchRequest.includesPropertyValues = true
fetchRequest.returnsObjectsAsFaults = false
fetchRequest.predicate = NSPredicate(format: "product == %#", temp)
fetchRequest.propertiesToFetch = ["name"]
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "id", ascending: true)]
do {
let personList = try context.fetch(fetchRequest) as! [People]
print(personList)
} catch let error as NSError {
print(error)
}
}

To fetch only specific properties the resultType of the request must be dictionaryResultType
private func getPeople(product: String) {
let fetchRequest = NSFetchRequest<NSDictionary>(entityName: "People")
fetchRequest.predicate = NSPredicate(format: "product == %#", product)
fetchRequest.resultType = .dictionaryResultType
fetchRequest.propertiesToFetch = ["name"]
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "id", ascending: true)]
do {
let personList = try context.fetch(fetchRequest) as! [[String:String]]
print(personList)
} catch {
print(error)
}
}
}

Related

CoreData Stops the saving after Heavyweight migration Xcode 14

Due to the enhancement in my project, I have done the heavyweight migration, now after heavy weight migration, CoreData is unable to store data it always return empty.
I have a class Function
class func insert(object: [String: Any], entityName: String) -> NSManagedObject? {
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: entityName, in: context)!
let managedObject = NSManagedObject(entity: entity, insertInto: context)
let keys = Array(entity.attributesByName.keys)
print("Keys:\(keys)\nobject:\(object)")
for (key, element) in object {
if keys.contains(key) {
managedObject.setValue(element, forKey: key)
}
}
do {
print(managedObject.isUpdated)
try context.save()
print(managedObject.isUpdated)
print("Success insert")
} catch {
print("Error in Insert: \(error)")
}
return managedObject
}
so I pass my Object with the key value pair in form of Dictionary, I pass the entityName to this function so it never return nil in managedObject While it always show false on print(managedObject.isUpdated) on both lines. Here is my console logs for saving data.
Keys:["contactIdentifier", "timeAndDate", "receiverId", "createdAt", "updatedAt", "i-----------g", "se---d", "duration", "senderId", "number", "name", "isFromiOS", "opponentsIds", "m-------d"]
object:["sessionID": "E1ECAB27-D312", "message": "--------", "contactIdentifier": "------- ", "I----p": "1", "contactNumbers": "------------,-----------", "V-----l": "1", "co------pe": "2", "createdAt": 2022-10-27 11:58:18 +0000, "opponentsIds": "---, ----"]
false
false
Success insert
updateCallInformation:<CallHistory2: 0x2835e99f0> (entity: CallHistory2; id: 0xa46b7d533bd5d14b <x-coredata://BAF5AFD6-8567-4485-8938-E13D3BD7B314/CallHistory2/p1>; data: {
contactIdentifier = "MDanishPK ";
createdAt = "2022-10-27 11:58:18 +0000";
duration = nil;
incomingOutgoing = nil;
isFromiOS = 0;
missedReceived = nil;
name = nil;
number = nil;
opponentsIds = nil;
receiverId = nil;
senderId = nil;
sessionID = "E1ECAB27-D312-4402-91D3-87AEBAC1A709";
timeAndDate = nil;
updatedAt = nil;
})
In console ---- I added intentially here for the privacy. There are some proper values and keys here.
If I revert my migration and goto the older branch using git than its working fine and save data properly. But I need heavy weight migration which I achieved using this article Kindly help me out and guide me what I have to do To save managedObject? and what I am doing wrong in saving managedObject? I changed all the table name but still its not saving data. On every launch I also lost the data.
Update Question
After Insert data I am using this fetch method, It always return me 0 against the array of [NSManagedObject]?
class func fetchList(entityName: String, predicate: NSPredicate? = nil, sortBy: [(key: String, ascending: Bool)]? = nil) ->
[NSManagedObject]? {
let context = CoreDataStack.context
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: entityName)
fetchRequest.predicate = predicate
if let sortedBy = sortBy {
var sortDescriptors = [NSSortDescriptor]()
for sortElement in sortedBy {
let sortDescriptor = NSSortDescriptor(key: sortElement.key, ascending: sortElement.ascending)
sortDescriptors.append(sortDescriptor)
}
fetchRequest.sortDescriptors = sortDescriptors
}
do {
let results = try context.fetch(fetchRequest)
return results
} catch {
print("Could not fetch: \(error)")
}
return nil
}

Swift 5 NSFetchRequest predicate when trying to lookup a String UUID

I have a string UUID coming into this method, to lookup an entity in CoreData that has UUID's saved as UUID type (Not String).
I keep getting "Fatal error: Unexpectedly found nil while unwrapping an Optional value" on line for the predicate.
func loadUser(uuid: String) -> [ExistingUsers2] {
let request : NSFetchRequest<ExistingUsers2> = ExistingUsers2.fetchRequest()
let uuidQuery = NSUUID(uuidString: uuid)
request.predicate = NSPredicate(format: "%K == %#", #keyPath(ExistingUsers2.uuid), uuidQuery! as CVarArg)
request.sortDescriptors = [NSSortDescriptor(key: "name", ascending: true)]
do {
existingUsersArray = try context.fetch(request)
print("Returned \(existingUsersArray.count)")
} catch {
print("Error fetching data from context \(error)")
}
return existingUsersArray
}
Any help? I haven't found anything here or Dr Google. TKS
You can replace your predicate with this:
guard let uuidQuery = UUID(uuidString: uuid) else { return [] } // no valid UUID with this code
request.predicate = NSPredicate(format: "%K == %#", #keyPath(ExistingUsers2.uuid), uuidQuery as CVarArg)
Everything else should work.
UPDATE
This is the code that finally worked, thanks for your help #André Henrique da Silva
func loadUser(uuid: String) -> [ExistingUsers2] {
let request : NSFetchRequest<ExistingUsers2> = ExistingUsers2.fetchRequest()
let uuidQuery = NSUUID(uuidString: uuid)
request.predicate = NSPredicate(format: "uuid == %#", uuidQuery! as CVarArg)
request.sortDescriptors = [NSSortDescriptor(key: "name", ascending: true)]
do {
existingUsersArray = try context.fetch(request)
} catch {
print("Error fetching data from context \(error)")
}
return existingUsersArray
}
Try this as your predicate: NSPredicate(format: "cid = %#", "\(id)")
where cid is the UUID in CoreData and id is the UUID you got from the string. Also do not use NSUUID.
Replace the uuidAttributeName with your attribute name and yourStringuuid with the your string that you want to convert into UUID type.
var uuid = UUID(uuidString: yourStringuuid)
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "ExistingUsers2")
fetchRequest.predicate = NSPredicate(format: "uuidAttributeName == %#",uuid)
let results = try context.fetch(fetchRequest)

Swift sort FetchRequest result by Turkish locale

How can I sort fetchResult by Turkish language, turkish characters sorted at the end of results.
let managedObjectContext = (UIApplication.shared.delegate as! AppDelegate).managedObjectContext
let fetch = NSFetchRequest<Contact>(entityName: "Contact")
let sortDescriptor = NSSortDescriptor(key: "firstName", ascending: true)
let sortDescriptors = [sortDescriptor]
fetch.sortDescriptors = sortDescriptors
do {
let list = try managedObjectContext.fetch(fetch)
} catch {
fatalError("Failed \(error)")
}
Working code:
let managedObjectContext = (UIApplication.shared.delegate as! AppDelegate).managedObjectContext
let fetch = NSFetchRequest<Contact>(entityName: "Contact")
let sortDescriptor = NSSortDescriptor(key: "firstName", ascending: true, selector: #selector(NSString.localizedCaseInsensitiveCompare))
let sortDescriptors = [sortDescriptor]
fetch.sortDescriptors = sortDescriptors
do {
let list = try managedObjectContext.fetch(fetch)
} catch {
fatalError("Failed \(error)")
}

Sort by date - Swift 3

I have a func getData() which retrieves core data entity, and I want to sort them by date. How can I apply NSPredicate or Predicate to get the data from CoreData sorted by date?
My core data entity:
Entity: Expenses
Attributes:
amount
category
date
func getData() {
let context = appDelegate.persistentContainer.viewContext
do {
expenses = try context.fetch(Expenses.fetchRequest())
} catch {
print("Cannot fetch Expenses")
}
}
Predicates are for filtering your search results. To sort them you need to use an NSSortDescriptor. Assuming you have an attribute on your Expenses entity called date of type Date:
func getData() {
let context = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<Expenses>(entityName: "Expenses")
let sort = NSSortDescriptor(key: #keyPath(Expenses.date), ascending: true)
fetchRequest.sortDescriptors = [sort]
do {
expenses = try context.fetch(fetchRequest)
} catch {
print("Cannot fetch Expenses")
}
}
EDIT: I should have mentioned that the sort selector is added in an array so that multiple sort descriptors can be added if needed. e.g. sort first by date, then by number of legs, then by volume, etc.
You need a sort descriptor to get all the objects in a specific order.
let sectionSortDescriptor = NSSortDescriptor(key: "date", ascending: true)
let sortDescriptors = [sectionSortDescriptor]
fetchRequest.sortDescriptors = sortDescriptors
My function to do a fetchRequest of data in Core Data and sort the results by date "timestamp" in descending order. "Ruta" is the name of the entity.
//Array of Ruta entity
rutas = [Ruta]()
func getData() {
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Ruta")
let sort = NSSortDescriptor(key: "timestamp", ascending: false)
request.sortDescriptors = [sort]
do {
rutas = try context.fetch(request) as! [Ruta]
} catch {
print("Fetching Failed")
}
}
In swift 4 or swift 5, you can use like
func sortlist(){
//1
guard let appDelegate =
UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext =
appDelegate.persistentContainer.viewContext
//2
let fetchRequest =
NSFetchRequest<NSManagedObject>(entityName: "User")
let sort = NSSortDescriptor(key: "date", ascending: false)
fetchRequest.sortDescriptors = [sort]
//3
do {
let langugeCodes = try managedContext.fetch(fetchRequest)
for result in langugeCodes as [NSManagedObject] {
var username:String = result.value(forKey: "username")! as! String
print("username==>",username)
}
} catch let error as NSError {
print("Could not fetch. \(error), \(error.userInfo)")
}
}
To get data which are lastly added at first, need to set key of sort descriptor as ObjectId.
let sectionSortDescriptor = NSSortDescriptor(key: #keyPath(Entity.ObjectId)
ascending: false) fetchRequest.sortDescriptors = [sectionSortDescriptor]

Core Data - How can I get the max value from an entity attribute (Swift)

Recipe
recipeID: Int
recipeName: String
I have an entity Recipe with an attribute recipeID.
How can I get the max(recipeID) as an Int value in Swift?
I'm new in swift, please help me.
Thanks in advance.
func fetchMaxID() {
let context = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
let fetchRequest = NSFetchRequest(entityName: "Recipe")
fetchRequest.fetchLimit = 1
let sortDescriptor = NSSortDescriptor(key: "recipeID", ascending: false)
fetchRequest.sortDescriptors = [sortDescriptor]
do {
let maxID = try [managedObjectContext?.executeFetchRequest(fetchRequest)].first
print(maxID)
} catch _ {
}
}
The way that Apple recommends and is the fastest is using NSExpressions. moc is a NSManagedObjectContext.
private func getLastContactSyncTimestamp() -> Int64? {
let request: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest()
request.entity = NSEntityDescription.entity(forEntityName: "Contact", in: self.moc)
request.resultType = NSFetchRequestResultType.dictionaryResultType
let keypathExpression = NSExpression(forKeyPath: "timestamp")
let maxExpression = NSExpression(forFunction: "max:", arguments: [keypathExpression])
let key = "maxTimestamp"
let expressionDescription = NSExpressionDescription()
expressionDescription.name = key
expressionDescription.expression = maxExpression
expressionDescription.expressionResultType = .integer64AttributeType
request.propertiesToFetch = [expressionDescription]
var maxTimestamp: Int64? = nil
do {
if let result = try self.moc.fetch(request) as? [[String: Int64]], let dict = result.first {
maxTimestamp = dict[key]
}
} catch {
assertionFailure("Failed to fetch max timestamp with error = \(error)")
return nil
}
return maxTimestamp
}
Learning from Ray Wenderlich's Core Data Tutorial
https://www.raywenderlich.com/115695/getting-started-with-core-data-tutorial/
func fetchMaxRecipe() {
let context = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
let fetchRequest = NSFetchRequest(entityName: "Recipe")
fetchRequest.fetchLimit = 1
let sortDescriptor = NSSortDescriptor(key: "recipeID", ascending: false)
fetchRequest.sortDescriptors = [sortDescriptor]
do {
let recipes = try context.executeFetchRequest(fetchRequest) as! [Recipe]
let max = recipes.first
print(max?.valueForKey("recipeID") as! Int)
} catch _ {
}
}
Hope this helps =).
func fetchMaxID() {
let context = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
let fetchRequest = NSFetchRequest(entityName: "Recipe")
fetchRequest.fetchLimit = 1
let sortDescriptor = NSSortDescriptor(key: "recipeID", ascending: false)
fetchRequest.sortDescriptors = [sortDescriptor]
do {
let results = try context.executeFetchRequest(fetchRequest) as! [Recipe]
if (results.count > 0) {
for result in results {
print(result.recipeID!)
}
} else {
print("No Recipe")
}
} catch let error as NSError {
// failure
print("Fetch failed: \(error.localizedDescription)")
}
}
This works also!
To check the max of an entity attribute you can simply use:
func findMaxRecipeID() -> Int {
let maxRecipeID = recipe?.value(forKeyPath: "recipe.#max.recipeID") as! Int
return maxRecipeID
}
You can use this to #sum, #max, #min, #count - saves quite a few lines of code.