iOS CoreData NSPredicate not clearing - ios

I'm writing an app that displays some data which changes based upon the day of the week it is. The context of the app is that it is for a conference that is upcoming. I want to display the calendar entries for that day. The event detail being stored in coredata.
What I'm using to create the NSPredicate is:
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"yyyy-MM-dd"];
NSDate *today = [NSDate date];
NSString *sunday = #"2011-12-04";
NSString *monday = #"2011-12-05";
NSString *tuesday = #"2011-12-06";
NSString *wednesday = #"2011-12-07";
NSInteger dayNumber = 1;
if ([[df stringFromDate:today] isEqualToString:sunday]) {
dayNumber = 2;
} else if ([[df stringFromDate:today] isEqualToString:monday]) {
dayNumber = 3;
} else if ([[df stringFromDate:today] isEqualToString:tuesday]) {
dayNumber = 4;
} else if ([[df stringFromDate:today] isEqualToString:wednesday]) {
dayNumber = 5;
}
NSExpression *lhs = [NSExpression expressionForKeyPath:#"day_number"];
NSExpression *rhs = [NSExpression expressionForConstantValue:[NSNumber numberWithInt:dayNumber]];
NSPredicate *equalToPredicat = [NSComparisonPredicate predicateWithLeftExpression:lhs
rightExpression:rhs
modifier:NSDirectPredicateModifier
type:NSEqualToPredicateOperatorType
options:0];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptorTime = [[NSSortDescriptor alloc] initWithKey:#"start_time" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:/*sortDescriptorDayNumber,*/ sortDescriptorTime, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
[fetchRequest setPredicate:equalToPredicat];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:managedObjectContext
sectionNameKeyPath:#"day_number"
cacheName:#"TodayCache"]
What I am seeing though is that when the date changes (ie: Saturday to Sunday) the data (displayed in a UITableView) doesn't get updated.
Thanks,
Matt.

The comment above is correct. Some more info.
1) The table will only update when [tableView reloadData] or one of the other reload methods is called
2) If you set a delegate for the NSFetchedResultsController you can respond to model changes and reload the table
3) The date changing is not a model change (unless you are updating the date in the model itself) and the NSFetchedResultsController will only update itself if it detects that it's managed object context has changed.
4) You need to do fetchedResultsController:performFetch:error when when the day changes b/c you are changing the predicate (i.e. the request). Otherwise, the table will reload with the old data.
To refresh the table based on the date changing, you need to detect the date change at whatever interval you like and reload the table at that time. One way you could do it is to calculate the interval between the current time and midnight and set a timer to fire after that interval. When the timer fires, change the predicate, performFetch with the results controller and reload the table. Then set a new timer until the next midnight. If you want this to be done in the users time zone, you'll need to take that into account also.
EDIT: clarified answer that a performFetch is necessary when the predicate changes

Related

NSFetchedResultsController for fetching date from coredata and display the date in titleForHeaderInSection of UITableview

I am storing a string input from textfield and its created dateandtime. I am storing date values in coredata with key messageDate which is a string data type. I am converting my date values to string and storing it in coredata.I am able to see the array of stored date and text values like below
timeAndDateMsgArr (
"2016-11-02 17:59 PM",
"2016-11-02 18:08 PM",
"2016-11-02 18:08 PM"
)
textArr (
"Hai",
"The",
"I'm"
)
I am able to see the stored text and its created date in UITableView by adding two labels in CustomCell. But i need to group the text by date. I have already tried many solutions and below is one of them
- (NSFetchedResultsController *)fetchedResultsController {
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"msgHistory" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *sort = [[NSSortDescriptor alloc]
initWithKey:#"messageDate" ascending:NO];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
[fetchRequest setFetchBatchSize:20];
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil
cacheName:#"Root"];
self.fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
NSLog(#"fetchcontroller %#",_fetchedResultsController);
return _fetchedResultsController;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
NSString *rawDateStr = [[[self.fetchedResultsController sections] objectAtIndex:section] name];
NSLog(#"raw %#",rawDateStr); //****** i am getting null value here************//
// Convert rawDateStr string to NSDate...
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"yyyy-MM-dd HH:mm:ss ZZ"];
NSDate *date = [formatter dateFromString:rawDateStr];
// Convert NSDate to format we want...
[formatter setDateFormat:#"d MMMM yyyy"];
NSString *formattedDateStr = [formatter stringFromDate:date];
return formattedDateStr;
}
Posting a pic to get some idea,current output is like
My expected output will be something like below, where i will show date in place of month
But i need to show messages group by date. I have tried apple sample code which suits my requirement where the date key is stored in date data type but in my case i am storing date in string data type. In my case i cannot change the data type because it effects the code. Is their any alternative solution or i need to change the data type? Any help will be really appreciated.
Apple sample code reference link
REF LINK
You can cleanly solve this by adding a non-optional, non-transient, String -messageDateSectionId attribute to your Core Data entity.
Have this -sectionId attribute be derived from the main -messageDate attribute; whenever you set -messageDate, also set -messageDateSectionId to your custom format.
Thus, you will be saving this derived -sectionId attribute along with your main attribute.
Next, when you create the -fetchController, set -sectionNameKeyPath to your -sectionId attribute. Everything in January 1-31, 2013 will have the same -sectionId, and so will be grouped together in the table.
For the -titleForHeaderInSection, you can simply return the -fetchController.sections[SECTION_NUMBER].name value to show your -sectionId string.

UIDatePicker and American/Canadian Timezone messing Up NSFetchRequest filter by Dates

I have a UITabBarController with two tabs (Timeline and Dates); both of which are UITableViewControllers. The user adds in information to these table views by tapping on a UINavigationBar button and then filling in information like Name, Event, Amount and Date. The first three are UITextFields and the date is a UIDatePicker. With the information saved to Core-Data, the UITableViewController gets updated using NSFetchedResultsControllers.
The model of CoreData is a Transaction Entity with a relationship to the Years Entity. I also have a Years Entity for checking the dates elsewhere (but more than just the years).
The second tab is a "Dates" tab which filters simply on the Years from the date, so if a user has 5 entries for the year 2014, it will only show 2014 once and then when the user clicks on the 2014 cell, they'll see all entries where the year = 2014. The same applies for other years.
Problem
I'm in the United Kingdom locale but my Mac that I coded the app on is in the US locale and I've just noticed a massive issue.
If you change the timezone to Singapore, or Asia (somewhere in front of UK in time) on the devie, the dates tab remains the same with what you left it as. However, if you change it to New York on the phone, or Mexico, or Canada (basically anytime behind the UK), then the Dates tab gets messed up with each year going down by one.
What I mean by this is, if you have 2014, 2013, 2012 in the Dates Tab and you're in the UK region, if you go to the New York timezone and go into the app, it now shows 2013, 2012 and 2011.
What is going on?
Here's some code in the "Save" Method of the Add Entry:
NSCalendar *yearCal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *yearComponent = [yearCal components:NSYearCalendarUnit fromDate:self.datePicker.date];
[yearComponent setTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"UTC"]];
NSDate *selectedYear = [yearCal dateFromComponents:yearComponent];
// Calling the year category to check whether it exists.
Years *years = (Years *)[Years matchingYear:selectedYear inManagedObjectContext:context];
transaction.years = years;
This calls a category on the Year Entity:
+ (Years *)matchingYear:(NSDate *)enteredYear inManagedObjectContext:(NSManagedObjectContext *)context
{
Years *years = nil;
// Creating a fetch request to check whether the year already exists, calling from the Add/DetailViewController.
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Years"];
request.predicate = [NSPredicate predicateWithFormat:#"yearOfEvent = %#", enteredYear];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"yearOfEvent" ascending:YES];
request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSError *error = nil;
NSArray *matchedYears = [context executeFetchRequest:request error:&error];
if (!matchedYears)
{
// No errors to handle
}
else if (![matchedYears count])
{
// If the year count is 0 then create it
years = [NSEntityDescription insertNewObjectForEntityForName:#"Years" inManagedObjectContext:context];
years.yearOfEvent = enteredYear;
}
else
{
// If the year exists, return it.
years = [matchedYears lastObject];
}
return years;
}
My UIDatePicker is set to the current date, so the user cannot pick a date in the future.
Here's the fetchResultsController code for the date tab:
- (NSFetchedResultsController *)fetchedResultsController
{
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
if (_fetchedResultsController != nil)
{
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Years" inManagedObjectContext:managedObjectContext];
fetchRequest.entity = entity;
NSPredicate *d = [NSPredicate predicateWithFormat:#"transactions.years.#count !=0"];
[fetchRequest setPredicate:d];
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:#"yearOfEvent" ascending:NO];
fetchRequest.sortDescriptors = [NSArray arrayWithObject:sort];
fetchRequest.fetchBatchSize = 20;
NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:nil];
self.fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
In my Save method, I notice I'm setting the timezone to UTC and the reason I did this was because if I didn't, when I went to another country and changed my timezone, it would add "2014" for each entry of 2014 in the Dates tab which was obviously wrong. But this is of course causing some issues here.
Requirement
I simply require the ability to keep the Dates tab the same, regardless of which timezone I'm in.
Key Points
There are a few reasons why the format is saved as it is in the Years, etc and that can't be changed because it impacts the entire app. The UIDatePicker is set to a UK Locale in the Storyboard and there are a few reasons for that. However, even with the locale set to "Default", the same issue occurs. Timezones in America and Canada remove a year, so 2014 becomes 2013, 2013 becomes 2012, 2012 becomes 2011 in the Dates tab. That's what doesn't make sense to me.
Any guidance on this would be really appreciated!
What is going on?
What's going on is that your requirement of keeping dates consistent regardless of timezone is not nearly so easy as you'd like. It's like this:
NSDate has no concept of time zone. It's basically an object wrapper for NSTimeInterval, measuring time since a reference date in UTC.
When you convert an NSDate to something human-readable, a time zone applies to the conversion. It has to apply, because when you ask for the date corresponding to the NSDate, you have to answer the question, the date, where, exactly?
Your initial save code sets you up for this problem:
NSCalendar *yearCal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *yearComponent = [yearCal components:NSYearCalendarUnit fromDate:self.datePicker.date];
[yearComponent setTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"UTC"]];
NSDate *selectedYear = [yearCal dateFromComponents:yearComponent];
If the selected date is today, the final NSDate is 410227200 seconds since the reference date, which in UTC corresponds to 00:00:00 on 1 January 2014. In time zones east of UTC it's one or more hours later, which is still 2014. In time zones west of UTC it's one or more hours earlier, which is still 2013. Every other detail of your problem stems from this fact.
If you care about the year, the best solution is to store the year, not an NSDate. Store 2014, 2013, 2012, etc as integers rather than as values implied by NSDate.
Incidentally this part of your question is completely irrelevant:
I'm in the United Kingdom locale but my Mac that I coded the app on is in the US locale and I've just noticed a massive issue.
What matters is the time zone on the device running the code, not the zone on the device used to compile and link that code.

Duplicate NSDates in Core Data, but not Duplicate NSStrings with the same code

I have a simple two-tabbed table view controller. The user presses the plus button and is taken modally to another view controller to add text into textfields and select a date from the UIDatePicker.
Everything is working well, except for a duplication problem with Core Data and my dates.
In the app, the first table view displays occasions based on the entry added to the text fields but I have put in some code to check that the occasion doesn't already exist before creating it. What this means is if you have "Wedding" as an occasion and you save, if you enter another entry with "Wedding" as the occasion, rather than creating two cells in the table view with Wedding, it creates just one and when you click on it, it goes another view controller to display all entries for Wedding.
That is working well.
However when it comes to the UIDatePicker and selecting dates, duplicated items are being created.
The model is:
Transaction Entity
Occasion Entity
Date Entity
The transaction Entity has a relationship to the Occasion and Date Entity.
Let's look at some code:
The save method in the modal view controller:
- (IBAction)save:(id)sender
{
NSManagedObjectContext *context = [self managedObjectContext];
Transaction *transaction = [NSEntityDescription insertNewObjectForEntityForName:#"Transaction" inManagedObjectContext:context];
Occasion *enteredOccasion = (Occasion *)[Occasion occasionWithTitle:self.occasionTextField.text inManagedObjectContext:context];
transaction.occasion = enteredOccasion;
// Code to save the date as well - shown below
}
That is calling the occasionWithTitle method which does the NSFetchRequest check:
+ (Occasion *)occasionWithTitle:(NSString *)title inManagedObjectContext:(NSManagedObjectContext *)context
{
Occasion *occasion = nil;
// Creating a fetch request to check whether the occasion already exists
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Occasion"];
request.predicate = [NSPredicate predicateWithFormat:#"title = %#", title];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"title" ascending:YES];
request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSError *error = nil;
NSArray *occasions = [context executeFetchRequest:request error:&error];
if (!occasions)
{
// Handle Error
}
else if (![occasions count])
{
// If the occasions count is 0 then let's create it
occasion = [NSEntityDescription insertNewObjectForEntityForName:#"Occasion" inManagedObjectContext:context];
occasion.title = title;
}
else
{
// If the object exists, just return the last object .
occasion = [occasions lastObject];
}
return occasion;
}
The code for the date picker, also in the save method is:
Date *date = (Date *)[Date occasionWithDate:self.datePicker.date inManagedObjectContext:context];
transaction.dates = date;
Which calls:
+ (Date *)occasionWithDate:(NSDate *)enteredDate inManagedObjectContext:(NSManagedObjectContext *)context
{
Date *date = nil;
// Creating a fetch request to check whether the date already exists
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Date"];
request.predicate = [NSPredicate predicateWithFormat:#"dateOfEvent = %#", enteredDate];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"dateOfEvent" ascending:YES];
request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSError *error = nil;
NSArray *dates = [context executeFetchRequest:request error:&error];
if (!dates)
{
// Handle Error
}
else if (![dates count])
{
// If the dates count is 0 then let's create it
date = [NSEntityDescription insertNewObjectForEntityForName:#"Date" inManagedObjectContext:context];
date.dateOfEvent = enteredDate;
}
else
{
// If the object exists, just return the last object .
date = [dates lastObject];
}
return date;
}
To me, the code looks the same but of course one is passing a NSString and one is passing a selected NSDate from a UIDatePicker.
The result is when it comes to the second tabbed table view (for dates), if I create a new Transaction with 2 December 2013 as the date, and then create another entry on 2 December 2013, it creates two separate cells in the table view for the same date, which of course is not right.
Any help on this maddening issue would be very appreciated!
EDIT: On a related note, I am taking the Date selected from the DatePicker and having that displayed as the Section title of the TableView with specific formatting. I am doing that using this code:
-(NSString *)sectionDateFormatter
{
return [NSDateFormatter localizedStringFromDate:self.dates.dateOfEvent
dateStyle:NSDateFormatterLongStyle
timeStyle:NSDateFormatterNoStyle];
}
And calling this in the sectionNameKeyPath.
Ok, I am offering a different answer because you asked in responding to #Tom whether you should diddle strings to make this work. The answer is emphatically no.
I've done a LOT of date programming in Java and in Objective-C. Java's date stuff (Date/Calendar) was so lame and inadequate, first another team came along (Joda-Time) and now it's being completely redone in 8 (JSR 310). In Java, there used to be easy ways to construct things with days, etc., but apparently, all that code was done outside the purview of the calendar so when the language blew up, it quickly became apparent that it was a mess and didn't work and a huge slew of deprecations resulted.
In Cocoa, however, you have the ability to do all these things by using date components. So you can take one date, then just pull out the components from it that you are interested in, and construct another date with just those components. That's the correct way to program around having values that you are not interested in (e.g. minutes, seconds, milliseconds).
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setDay:6];
[components setMonth:5];
[components setYear:2004];
NSInteger weekday = [components weekday];
Even if you are just going to be doing a little date programming, consider watching the WWDC 2013 session. It was surprisingly, not one of the best sessions, but it does cover some things that are a hassle.
But the date Date and Time Programming Guide is must reading, and really outstanding.
Those dates aren't really the same, they're just on the same day. UIDatePicker gives you a full NSDate, which includes the time of day. The time of day seems to be fixed when you load the picker, but if you load the same view more than once, you'll get different times. For example, when messing around with Apple's UICatalog demo, I get 2013-12-03 17:20:11 +0000 when selecting December 3. If I back out via the navigation controller and then reload the same view, I get 2013-12-03 17:20:22 +0000. Those are the same date, as the term is usually used, but they're not the same NSDate. They won't match in a predicate even though they're both on December 3.
If you're only interested in the date, not the time of day, you need to convert the NSDate from the picker into something that only has the date, with either known fixed time values or no time values. A couple of possibilities:
Use NSDateFormatter to get a string for the date, using a date format that only includes the year, month, and day.
Use NSCalendar to get the year, month, and day components for the NSDate that you get from the picker. Then either just store those values in your model, or convert those back into an NSDate with fixed, known values for the time of day (maybe make them all zero).
The second will be quicker when fetching values (since you'll be filtering on numeric values). The first may be easier to write, but filtering on string values will be slower.
If using the date components approach (recommended) do something like this with the date you get from the picker:
NSDateComponents *components = [[NSCalendar currentCalendar]
components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit
fromDate:date];
NSInteger year = components.year;
NSInteger month = components.month;
NSInteger day = components.day;
Then save those three values in your data model instead of an NSDate. Or combine them into a single integer value and save that:
NSInteger dateIndex = year * 10000 + month * 100 + day;
That will give you an integer value of 20131202 for December 2, 2013.
Whichever approach you use, do the same thing when fetching.

Changing Core Data Attribute from NSString to NSDate and getting this functionality to work using a Date Picker

I am working through my first app and need some advice on how to approach this next task and issue. The premise of the app is the user has a table view, clicks on a plus button in the navigation bar and is presented with text fields to insert information. Upon clicking on save, that gets saved to the core data and displayed in the table view.
The table view is sectioned. Right now, I have the "date" being represented as a NSString, just to get my app off the ground, but I need to change this to a DatePicker. The sections' are based on the Dates.
I have a Core Data Model as follows:
Transaction Entity
Person Entity
Occasion Entity
Date Entity
The Transaction Entity has a relationship to each of the other entities here.
As mentioned, at first, to get my app working and off the ground, I made the Date Entity have a dateOfEvent attribute which was a NSString rather than a NSDate but of course that will not work in the long run.
I have changed my model to NSDate for this attribute and regenerated the NSManagedObject Subclasses.
Independently, I have a DatePicker working without any issues but it outputs the information to a String in a textfield.
What I want to achieve now is to use the DatePicker, select a date and have that saved to the Core Data Date Entity (dateOfEvent attribute) which I can then use in the table view as the section titles.
Here is my code for saving in the view controller:
- (IBAction)save:(id)sender
{
NSManagedObjectContext *context = [self managedObjectContext];
Transaction *transaction = [NSEntityDescription insertNewObjectForEntityForName:#"Transaction" inManagedObjectContext:context];
Date *enteredDate = (Date *)[Date occasionWithDate:self.dateTextField.text inManagedObjectContext:context];
transaction.dates = enteredDate;
// Code to save Person, Occasion, etc.
}
The enteredDate is calling a specific occasionWithDate method:
+ (Date *)occasionWithDate:(NSString *)enteredDate inManagedObjectContext:(NSManagedObjectContext *)context
Date *date = nil;
// Creating a fetch request to check whether the name of the person already exists
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Date"];
request.predicate = [NSPredicate predicateWithFormat:#"dateOfEvent = %#", enteredDate];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"dateOfEvent" ascending:YES];
request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSError *error = nil;
NSArray *dates = [context executeFetchRequest:request error:&error];
if (!dates)
{
// Handle Error
}
else if (![dates count])
{
// If the person count is 0 then let's create it
date = [NSEntityDescription insertNewObjectForEntityForName:#"Date" inManagedObjectContext:context];
date.dateOfEvent = enteredDate;
}
else
{
// If the object exists, just return the last object .
date = [dates lastObject];
}
return date;
}
This does a fetchRequest to ensure I am either returning an existing date or adding a new one if that does not exist.
That is the behaviour I would like here, but of course, that method is passing a String and I need to pass a date.
With this in mind, how do I go about selecting the value of the DatePicker, adding it to the Core Data database in the same way as above (checking whether the date exists) and having this displayed in the sections of the Table View?
The reason I want to check if the date exists is because if there is an event on the 2nd December 2013, it'll be unique. However if I create another event on the 2nd December 2013, I'd want it to use the existing 2nd December, rather than create a second entry for 2nd December. The reason is my app has a tab view where the second tab is predicated by dates and so I would not want two separate 2nd December there.
This is a side note. The main thing I would like to achieve is, use the Date Picker and save the selected value to Transaction.dates.dateOfEvent to Core Data.
I know if I were to do something like date.dateOfEvent = [NSDate date]; it would be assigning the date and time now. That is not what I want here.
Any assistance would be massively appreciated.
Thanks,
EDIT: Adding in UIDatePicker Code - this first code snippet below is for saving to the textField when using NSString as the attribute
In viewDidLoad
[self.datePicker addTarget:self action:#selector(getSelection:) forControlEvents:UIControlEventValueChanged];
-(void)getSelection:(id)sender
{
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterLongStyle];
[dateFormatter setTimeStyle:NSDateFormatterNoStyle];
NSDate *date = [self.datePicker date];
NSString *formattedDateString = [dateFormatter stringFromDate:date];
self.dateTextField.text = formattedDateString;
}
Edit: The save to core data method is above - it calls occasionWithDate method and checks if the date exists already when the dateOfEvent attribute is NSString. Because I need to sort by ascending dates in the table view, I have changed the dateOfEvent to be a NSDate format
To get the current date and time, I'm putting this code in the save method:
Date *date = [NSEntityDescription insertNewObjectForEntityForName:#"Date" inManagedObjectContext:context];
date.dateOfEvent = [NSDate date];
transaction.dates = date;
That is giving me the current date and time. What I want is for the user to select a date using the UIDatePicker and whatever date is selected, for that to be saved as the dateOfEvent attribute of the Date entity which I can then use in the Sections of the Table view.
To get NSDate from your UIDatePicker object use UIDatePicket date property.
date
The date displayed by the date picker.
#property(nonatomic, retain) NSDate *date
Discussion
The default is the date when the UIDatePicker object is created. The date is ignored in the mode UIDatePickerModeCountDownTimer; for that mode, the date picker starts at 0:00. Setting this property does not animate the date picker by spinning the wheels to the new date and time; to do that you must use the setDate:animated: method.
check Apple UIDatePicker documentation

How do I query a core data table containing an NSDate attribute to retrieve a distinct list of years?

I have a table with a single NSDate attribute. The table contains records whose NSDate attribute is populated with various dates. I need to create a request that retrieves only the distinct years within this NSDate attribute.
For example, if my table contains the following entries:
date |stringValue
01-20-2013|"foo"
03-23-2013|"bar"
04-24-2014|"baz"
The core data fetch request will return the following in an array:
2013
2014
I would recommend you fetch the data from Core Data using an NSFetchRequest and then use an NSDateFormatter to present the data in the required format to the user interface, or where ever it needs to be used. I'm not sure it's possible to do what you want purely within Core Data, or at least if it is, the above might be simpler. Always go with The Simplest Possible Thing.
First you have to fetch distinct values like this
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:#"MyEntity"];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"MyEntity" inManagedObjectContext:self.managedObjectContext];
// Since you only want distinct date, only ask for the 'date' property.
fetchRequest.resultType = NSDictionaryResultType;
fetchRequest.propertiesToFetch = [NSArray arrayWithObject:[[entity propertiesByName] objectForKey:#"date"]];
fetchRequest.returnsDistinctResults = YES;
// Now it should yield an NSArray of distinct values.
NSArray *distinctDateArray = [self.managedObjectContext executeFetchRequest:fetchRequest error:nil];
then usig NSDateFormatter get only exact year values you want like this.
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy"];
for(NSDate *date in distinctDateArray)
{
NSLog(#"Date: %#", [dateFormatter stringFromDate:date]);
}

Resources