I am extracting data from the past week using CoreData. It all works fine for days when some data is stored. However, when no data is stored, the program crashes. How can I handle this error?
for i in 0...6 { // Get every day in the past week
let appDel = (UIApplication.sharedApplication().delegate as! AppDelegate)
let context: NSManagedObjectContext = appDel.managedObjectContext
let request = NSFetchRequest(entityName: "Pulser")
request.returnsObjectsAsFaults = false
let calendar = NSCalendar.currentCalendar()
let now = NSDate()
let beginningOfToday = calendar.startOfDayForDate(now)
let previousDay = calendar.startOfDayForDate(calendar.dateByAddingUnit(.Day, value: -i, toDate: beginningOfToday, options: [])!)
let previousPreiviousDay = calendar.startOfDayForDate(calendar.dateByAddingUnit(.Day, value: -i - 1 , toDate: beginningOfToday, options: [])!)
request.predicate = NSPredicate(format:"(date >= %#) AND (date < %#)", previousPreiviousDay, previousDay)
do {
let results = try context.executeFetchRequest(request) as! [Pulser]
pulseArray.append(meanValue(results)) // if more than one value stored for each day, take the mean value of it
}
catch let error as NSError {
print(error)
}
}
It works like a charm now, thanks.
if results.count > 0 {
pulseArray.append(meanValue(results))
}
Related
I have a .xcdatamodel in Core Data with the Entity Content and the Attributes dateCreated Type Date and text1 Type String.
//CREATE
func createData() {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let managedContext = appDelegate.persistentContainer.viewContext
let contentEntity = NSEntityDescription.entity(forEntityName: "Content", in: managedContext)!
let content = NSManagedObject(entity: contentEntity, insertInto: managedContext)
content.setValue(Date(), forKey: "dateCreated")
content.setValue("someText", forKey: "text1")
do {
try managedContext.save()
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
}
//READ
func readData() {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let managedContext = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Content")
fetchRequest.predicate = NSPredicate(format: "text1 = %#", "some text")
do {
let result = try managedContext.fetch(fetchRequest)
for data in result as! [NSManagedObject] {
print(data.value(forKey: "dateCreated") as! Date)
print(data.value(forKey: "text1") as! String)
}
} catch {
print("Failed")
}
}
if I print dateCreated, it gives: 2020-03-12 10:20:42 +0000
My question is: how can I read and filter by date? Only date, not time. For instance 2020-03-12 or any other date without time:
fetchRequest.predicate = NSPredicate(format: "dateCreated = %#", ?????)
In CreateData() you're storing the date by using Date(). So that it will be stored in you're database with the format yyyy-MM-dd HH:mm:ss ZZZZ. That's why it prints this 2020-03-12 10:20:42 +0000
Change from
fetchRequest.predicate = NSPredicate(format: "text1 = %#", "some text")
to
fetchRequest.predicate = NSPredicate(format: "dateCreated = %#", Date())
if you using this predicate instead of text1, the core data will give you result with Date and it'll be difficult to filter if there is time. So you have to insert the date by changing its format to yyyy-MM-dd
You can change the current date format by using DateFormatter().
//Needed date format
let dateFormat = DateFormatter()
dateFormat.dateFormat = "yyyy-MM-dd"
let formattedDate = dateFormat.string(from: Date())
So try by inserting the Date() by changing its format
//in CreateData()
content.setValue(formattedDate, forKey: "dateCreated")
//in ReadData()
fetchRequest.predicate = NSPredicate(format: "dateCreated = %#", formattedDate)
A old classic question but I got.
func callThisDay(startDate:Date, endDate:Date) -> [Login]{
var datas = [Login]()
let fetchRequest:NSFetchRequest<Login> = Login.fetchRequest()
let predicate = NSPredicate(format: "date >= %# AND date < %#", argumentArray: [startDate, endDate])
fetchRequest.predicate = predicate
do{
let allData = try viewContext.fetch(Login.fetchRequest())
for data in allData{
datas.append(data as! Login)
}
}catch{
print(error)
}
return datas
}
And it always return all data. How can I just got a day?
Of course it always returns all data because you are ignoring the custom fetch request.
Replace
let allData = try viewContext.fetch(Login.fetchRequest())
with
let allData = try viewContext.fetch(fetchRequest)
The method can be simplified
func callThisDay(startDate:Date, endDate:Date) -> [Login] {
let fetchRequest : NSFetchRequest<Login> = Login.fetchRequest()
fetchRequest.predicate = NSPredicate(format: "date >= %# AND date < %#", startDate as NSDate, endDate as NSDate)
do {
return try viewContext.fetch(fetchRequest)
} catch {
print(error)
return []
}
}
I am fairly new to Swift & hoping someone knows the answer to this - nothing I try seems to work!
I have a Swift app which has a Core Data entity called "Drink" with 2 keys: a Date & then one called "drinkWater" which stores a value of "1" when a button is pushed.
I am trying to write a separate function where I can check if an entry exists for todays date and, if so, perform an action (in this case change an imageview).
I realise the below isn't the answer but it's as far as I got! Basically I can get all of the entries based on the value of drinkWater (this would need to be by Date I am guessing?) and I can get today's date all printing to the console. Now I'm stuck ...
private func updateMyImageView() {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Drink")
request.predicate = NSPredicate(format: "drinkWater = %#", "1")
request.returnsObjectsAsFaults = false
do {
let result = try context.fetch(request)
for data in result as! [NSManagedObject] {
print(data.value(forKey: "timestamp") as! Date)
}
} catch {
print("Failed")
}
let dateNow = Date()
print("Date is \(dateNow)")
}
This returns:
2018-12-29 01:27:27 +0000
Date is 2018-12-29 12:21:21 +0000
Any ideas on how to turn this all into the correct function would be greatly appreciated!!
You need to use a date range from start of day to end of day (midnight to midnight) in a compound predicate. Here is a solution based on a similar SO question
var calendar = Calendar.current
calendar.timeZone = NSTimeZone.local
let dateFrom = calendar.startOfDay(for: Date())
let dateTo = calendar.date(byAdding: .day, value: 1, to: dateFrom)
let fromPredicate = NSPredicate(format: "timestamp >= %#", dateFrom as NSDate)
let toPredicate = NSPredicate(format: "timestamp < %#", dateTo! as NSDate)
let waterPredicate = NSPredicate(format: "drinkWater = %#", "1")
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Drink")
request.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [waterPredicate, fromPredicate, toPredicate])
Thank you for all of your help. I have it all working now. My final code is:
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
var calendar = Calendar.current
calendar.timeZone = NSTimeZone.local
let dateFrom = calendar.startOfDay(for: Date())
let dateTo = calendar.date(byAdding: .day, value: 1, to: dateFrom)
let fromPredicate = NSPredicate(format: "timestamp >= %#", dateFrom as NSDate)
let toPredicate = NSPredicate(format: "timestamp < %#", dateTo! as NSDate)
let waterPredicate = NSPredicate(format: "drinkWater = %#", "1")
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Drink")
request.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [waterPredicate, fromPredicate, toPredicate])
do {
let result = try context.fetch(request)
for data in result as! [NSManagedObject] {
print(data.value(forKey: "timestamp") as! Date)
drinkMoreButton.setBackgroundImage(UIImage(named: "watericonselected.png"), for: UIControlState.normal)
}
} catch {
print("Failed")
}
i need to insert the days of the week Mon -> Sunday into core data, because you cant set data into core data from interface builder im doing this when the app first opens like this...
let firstLaunchCheck = NSUserDefaults(suiteName: "nonya-buisness ;)")
if firstLaunchCheck?.boolForKey("firstLaunch") == false {
print("First Launch")
let appDel = NSApplication.sharedApplication().delegate as! AppDelegate
let context = appDel.managedObjectContext
let addDay = NSEntityDescription.insertNewObjectForEntityForName("Weekdays", inManagedObjectContext: context)
let dayIndex = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
var dayNumber = 0
for day in dayIndex {
print(day)
addDay.setValue(day, forKey: "dayName")
addDay.setValue(dayNumber, forKey: "dayNumber")
if dayNumber >= 5 {
addDay.setValue(true, forKey: "dayHoliday")
} else {
addDay.setValue(false, forKey: "dayHoliday")
}
do {
try context.save()
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
}
dayNumber++
}
firstLaunchCheck?.setBool(true, forKey: "firstLaunch")
firstLaunchCheck?.synchronize()
} else {
print("App has already been opened")
}
Im storing the dayName and the dayNumber (eg, Wednesday is 2) and also adding wheather or not the day is a holiday or not. By default its set to Saturday and sunday (This can be changed by the user later)
Next in my view did load method im trying to load my data, this is where im getting stuck i think...
var TimetableData = [NSManagedObject]()
super.viewDidLoad() {
let appDel = NSApplication.sharedApplication().delegate as! AppDelegate
let context = appDel.managedObjectContext
let request = NSFetchRequest(entityName: "Weekdays")
request.sortDescriptors = [NSSortDescriptor(key: "dayNumber", ascending: false)]
do {
let results = try context.executeFetchRequest(request)
TimetableData = results as! [NSManagedObject]
print(TimetableData.count)
DayTableView.reloadData()
} catch {
print("There was a problem retrieving saved data")
}
}
The actually representing the data in a table view i dont think is the problem, but heres the code anyway.
if tableView == DayTableView {
let savedData = TimetableData[row]
let cell : NextDayCell = DayTableView.makeViewWithIdentifier("nextDayCell", owner: self) as! NextDayCell
if savedData.valueForKey("dayHoliday") as? Bool == true {
cell.cellDayString.stringValue = savedData.valueForKey("dayName") as! String + " Weekday"
} else {
cell.cellDayString.stringValue = savedData.valueForKey("dayName") as! String
}
cell.dayNumberS.stringValue = "\(day)"
day++
return cell
}
For some reason all this code is only loading 1 thing from core data, and that is Sunday. Help me ;P thanks people in advance
You do one insertNewObjectForEntityForName and change the properties of this object for each day. The solution is to do insertNewObjectForEntityForName for each day.
If the question here is really about CoreData, then I'm sure there will be another answer very soon.
If the real requirement is about accessing the days of the week, there is a simpler approach
let dateFormatter = NSDateFormatter()
// dateFormatter.weekdaySymbols = "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
for dayIndex in days
{
print(dateFormatter.weekdaySymbols[dayIndex])
}
I'm using a timeIntervalSinceNow function to determine the difference between a certain time and the current time. I have used the "ZeroFormattingBehaviour" to .DropAll to get rid of any 0's in the date. However I want to make it so the difference doesn't include the seconds difference. For example if the difference is 2 days , 5 hours , 25min and 40 sec I want it to only show 2days,5h,25min. (e.g. excluding the seconds part) Is there any way to do so?
Code is as follows:
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let fetchRequest = NSFetchRequest(entityName: "Values")
let sortDescriptor = NSSortDescriptor(key: "time", ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor]
do {
let results = try managedContext.executeFetchRequest(fetchRequest)
Values = results as! [NSManagedObject]
for result in results as! [NSManagedObject] {
times = result.valueForKey("time") as! String
let timeFormatter = NSDateFormatter()
timeFormatter.locale = NSLocale.currentLocale()
timeFormatter.dateFormat = "HH:mm dd/MM/yy"
let otherTime = timeFormatter.dateFromString(times)
let dateComponentsFormatter = NSDateComponentsFormatter()
dateComponentsFormatter.unitsStyle = NSDateComponentsFormatterUnitsStyle.Abbreviated
dateComponentsFormatter.zeroFormattingBehavior = NSDateComponentsFormatterZeroFormattingBehavior.DropAll
let difference = otherTime?.timeIntervalSinceNow
let diffAbs = abs(difference!)
let stringDiff = dateComponentsFormatter.stringFromTimeInterval(diffAbs)
// "\n" skips a line in the text
TimerLabel.text = stringDiff!
}
} catch let error as NSError {
TimerLabel.text = "There seems to be an error. Please try again later"
print("Could not fetch \(error), \(error.userInfo)")
}
Thanks
Specify the units you want to display
dateComponentsFormatter.allowedUnits = [.Day, .Hour, .Minute]