swift core data executeFetchRequest always crash with propertiesToGroupBy - swift

i am having a problem with executeFetchRequest when i use propertiesToGroupBy. I need to fetch dates(saved as string) but similar dates should be avoided, so that i get unique date array. below is the code i used
var arrDates: NSArray = NSArray()
let fetchRequestDates = NSFetchRequest(entityName: "Schedule")
fetchRequestDates.propertiesToGroupBy = ["date"]
fetchRequestDates.propertiesToFetch = ["date"]
fetchRequestDates.resultType = .DictionaryResultType
do {
let result = try managedContext.executeFetchRequest(fetchRequestDates)
arrDates = result as NSArray
} catch {
NSLog("Failed to fetch dates: \(error)")
}
the execution doesn't go further
let result = try managedContext.executeFetchRequest(fetchRequestDates)
and causing SIGBART. If I comment
fetchRequestDates.propertiesToGroupBy = ["date"]
it works but will fetch duplicate dates too. what is the work around?

Related

Distinct value from core data swift

i want to get distinct dates from core data.
with this code fetchRequest.returnsDistinctResults = true is not working.
it is still showing all values.
guard let appDelegate =
UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Journal")
fetchRequest.propertiesToFetch = ["dateAsNumber"]
fetchRequest.returnsDistinctResults = true
do {
dateListSquare = try managedContext.fetch(fetchRequest)
} catch let error as NSError {
print("Could not fetch. \(error), \(error.userInfo)")
}
If you want distinct results, you need to set the fetch request's result type to NSFetchRequestResultType.dictionaryResultType. You can't fetch managed objects and get distinct results, since there might be more than one managed object with the same value.
That would look something like
let fetchRequest: NSFetchRequest<NSDictionary> = NSFetchRequest(entityName: "Journal")
fetchRequest.propertiesToFetch = ["dateAsNumber"]
fetchRequest.returnsDistinctResults = true
fetchRequest.resultType = .dictionaryResultType
The result will be an array of dictionaries. Each will have one key per entry in propertiesToFetch (just one in this case).
If you use propertiesToFetch without dictionaryResultType, you affect how faulting works but not the contents of the result. Using returnsDistinctResults only works if you also use propertiesToFetch, so it's also affected by whether you use dictionaryResultType.

Swift Core Data Variable Issue

I am having a syntax issues I just cannot figure out. I do not have a strong Swift back ground, so the answer my be easy (I hope.) So, here is the snippet:
public func getLatestDate()-> NSDate? {
var request = NSFetchRequest()
var entity = NSEntityDescription.entityForName("Event", inManagedObjectContext: self.managedObjectContext)
request.entity = entity
let sortDescriptor = NSSortDescriptor(key: "timeStamp", ascending: false)
let sortDescriptors = [sortDescriptor]
request.sortDescriptors = sortDescriptors
var error: NSError? = nil
do {
let results = try self.managedObjectContext.executeFetchRequest(request)
} catch {
fatalError("Failed to fetch employees: \(error)")
}
var date: NSDate?
if results != nil {
let managedObject: NSManagedObject = results![0] as NSManagedObject
date = managedObject.valueForKey("timeStamp") as? NSDate
}
return date
}
The problem is that if results != nil and the results on the following line are throwing an error stating:
Use of unresolved identifier 'results'
How do I resolve this issue?
Thank you.
-Matt
You're declaring results here:
do {
let results = try self.managedObjectContext.executeFetchRequest(request)
} catch {
fatalError("Failed to fetch employees: \(error)")
}
So you can see that it's being done within a do-catch block. That means that where you try to use it is out of the scope where it was defined, so it can't see it at all. By the time you get to if results != nil, it's already gone out of scope and is gone.
in addition to Gavin: this will work cause of the reason, thar Gavin mentioned
do {
let results = try self.managedObjectContext.executeFetchRequest(request)
if results != nil {
let managedObject: NSManagedObject = results![0] as NSManagedObject
date = managedObject.valueForKey("timeStamp") as? NSDate
}
} catch {
fatalError("Failed to fetch employees: \(error)")
}

saving, deleting and fetching data from a one to many relationship core data

I have created a data model like so:
I have this code for a fetch request:
func roundFetchRequest() -> NSFetchRequest {
let fetchRequest = NSFetchRequest(entityName: "Customer")
print("Check here: \(myRoundIndexPath)")
//let predicate : NSPredicate = NSPredicate(format: "custRoundRel = %#", frc2.objectAtIndexPath(myRoundIndexPath!) as! RoundName) //ASSUME THIS IS CORRECT
let sortDescriptor = NSSortDescriptor(key: "c2fna", ascending: true)
//fetchRequest.predicate = predicate
fetchRequest.sortDescriptors = [sortDescriptor]
return fetchRequest
}
My commented out code does not give an error, but I cannot seem to save a customer to the RoundName instance. When I save a customer with its attributes, I have used this code:
func newCust() {
let cont = self.context
let newCustomer = NSEntityDescription.entityForName("Customer", inManagedObjectContext: cont)
let aCust = Customer(entity: newCustomer!, insertIntoManagedObjectContext: cont)
aCust.c2fna = firstName.text
aCust.c3lna = lastName.text
aCust.c4tel = tel.text
aCust.c5mob = mob.text
aCust.c6ema = email.text
aCust.c7hsn = houseNo.text
aCust.c8fir = street.text
aCust.c9sec = secondLine.text
aCust.c10ar = area.text
aCust.c11pc = postcode.text
aCust.c12cos = cost.text
aCust.c13fq = frequencyNumber.text
aCust.c14fqt = frequencyType.text
let DF = NSDateFormatter()
aCust.c15das = DF.dateFromString(startDate.text!)
//Do Pics in a minute & next date in a minute
aCust.c17notes = notes.text
//print("Desc = \(picRound.image?.description)")
do {
try context.save()
print("Save Successful")
} catch {
print("Save Unsuccessful")
}
}
What is the code to link this customer with the correct Round?
Thanks, I am very new to core data and really would appreciate any help.
Yes, you use a predicate on your fetch request, with a format like
NSPredicate(format:"custRoundRel = %#", xxxx)
where xxxx is the Round instance.
You can also just use the roundCustRel relationship depending on what you want to do with the Customer instances and how many there are.
You create Customer objects in the same way you create other managed objects. To link a customer with the correct Round object, just set the to-one relationship (Core Data will automatically set the reverse relationship for you).
newCustomer.round = round
// or, with your arcane attribute names
newCustomer.custRoundRel = theDesiredRoundObject
To get to the customers of one specific round, you do not need fetch requests or predicates.
round.customers
// or, with your arcane attribute names
round.roundCustRel

Core Data EXC_BREAKPOINT

Here is the code that I have used throughout my project without any issues:
var results: NSArray = context.executeFetchRequest(request, error: &error)!
Yet it's crashing! Any ideas why??
More code:
//now get old current and revoke that
var context:NSManagedObjectContext = self.appDel.managedObjectContext!
var request = NSFetchRequest(entityName: "DownloadedCharacters")
request.returnsObjectsAsFaults = false
request.predicate = NSPredicate(format: "isCurrent = %#", true)
var results: NSArray = context.executeFetchRequest(request, error: &error)!
//error check
if results.count == 1 {
//good
let object:NSManagedObject = results[0] as NSManagedObject
object.setValue(false, forKey: "isCurrent")
println("Revoked old current Object, 1")
//update currents
//find the new object in storage based off saved name
let lookupName = cell.cellData?.valueForKey("saveName") as String
var request2 = NSFetchRequest(entityName: "DownloadedCharacters")
request2.returnsObjectsAsFaults = false
request2.predicate = NSPredicate(format: "saveName = %#", lookupName)
var results2:NSArray = context.executeFetchRequest(request2, error: &self.error)!
if results2.count == 1 {
let object = results2.firstObject as NSManagedObject
object.setValue(true, forKey: "isCurrent")
println("Updated new current")
} else {
println("Fatal error in retreving object for Core Data. Count = \(results.count).")
}
//now update the section of the table
tableView.reloadSections(NSIndexSet(index: 1), withRowAnimation: UITableViewRowAnimation.Automatic)
}
Very frustrating. Also, AFTER the problematic line, println("Revoked old current Object, 1") IS being called and IS printing to console.......... any help would be much appreciated

Issue: Saving Json data to Core Data

I am trying to learn how to read data from a blog and save it to core data but the save is not working as intended. There are 4 blog entries and I expect to have 4 different entries in core data. Please see the code below and let me know where i went wrong:
let task = session.dataTaskWithURL(url!, completionHandler:{(data , response, error) -> Void in
if (error != nil){
println(error)
}else{
var jsonResult:NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers, error: nil) as NSDictionary
var managedObjectContext = (UIApplication.sharedApplication().delegate as AppDelegate).managedObjectContext!
let newBlog = NSEntityDescription.insertNewObjectForEntityForName("BlogDetails",inManagedObjectContext:managedObjectContext) as NSManagedObject
var dateFormater = NSDateFormatter()
dateFormater.dateFormat = "yyyy-MM-dd HH:mm:ss" //"yyyy-MM-dd"
var readRequest = NSFetchRequest(entityName: "BlogDetails")
for var i = 0; i < ((jsonResult["items"] as? NSArray)?.count)!; i++ {
var item = jsonResult["items"]![i] as NSDictionary
var blogAuthorDirectory = item["author"]! as NSDictionary
var blogAuthor = blogAuthorDirectory["displayName"] as NSString
var blogAuthorImageDirectory = blogAuthorDirectory["image"] as NSDictionary
// concatenate String
var blogAuthorImage = blogAuthorImageDirectory["url"] as NSString
var blogAuthorImageUrl = ("https:" + blogAuthorImage)
var title = item["title"] as String
// convert date from String
var publishedDate:NSDate = dateFormater.dateFromString(stringTmp as NSString)!
// read content
var content = item["content"] as? NSString
// Write it to core data
newBlog.setValue(blogAuthorImageUrl, forKey: "image")
newBlog.setValue(blogAuthor, forKey: "author")
newBlog.setValue(title, forKey: "title")
newBlog.setValue(publishedDate, forKey: "publisheddate")
managedObjectContext.save(nil)
var results = managedObjectContext.executeFetchRequest(readRequest, error: nil)
println(results)
}
}
})
task.resume()
following are the entries in result in the last iteration:
1. It only has 3 dictionary counts out of which values in first 2 count has all items as nil. how is that being generated?
2. With every iteration, it overwrites value in last count and doesn't append it.
Thanks for your help.
If you want to append objects to your CoreData, you need to do insertIntoManagedObjectContext before you call the managedContext.save(nil) method.
However, your
let newBlog = NSEntityDescription.insertNewObjectForEntityForName("BlogDetails",inManagedObjectContext:managedObjectContext) as NSManagedObject
is declared outside of your for loop, so probably no new blog created after each iteration.