MagicalRecord - fetch objects grouped by month/year - iphone

I have a number of Game objects, each one having a date parameter.
In my controller I want to fetch those games, grouped by the month-year combination of their dates - so I can get a list of months, and for each month - a list of the games that happened in that month.
Is there a simple solution for this, without having to modify my CoreData model?

Custom Section Titles with NSFetchedResultsController - this sample project shows how to do this (if I understood you correctly). Obviously, it doesn't use MagicalRecord, but it should be easy to port to MR.

this worked for me
in your
model.h
add
-(NSString *)yearMonth;
and
model.m
-(NSString *)yearMonth
{
NSDateFormatter *dateFormatter = [NSDateFormatter new];
[dateFormatter setDateFormat:#"yyy-MM"];
NSString *formattedDateString = [dateFormatter stringFromDate:self.eventDate];
return formattedDateString;
}
Then call a MR_Fetch by group method like this:
NSFetchedResultsController *frc = [model MR_fetchAllGroupedBy:#"yearMonth" withPredicate:nil sortedBy:#"eventDate" ascending:NO];

Related

NSPredicate for max(arrayOfNSDates)

I got problem with NSPredicate.
I got some engine where the predicates are constructed from a definition coming from a web service.
I use somethning like that:
[NSPredicate predicateWithFormat:#"max({1,2,3})==3"]
it's great, but I need max function for NSDate objects.
Here http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSExpression_Class/Reference/NSExpression.html#//apple_ref/doc/uid/TP30001190 is wrote that max() function can get only array containings objects representing numbers.
Is there any solution to use this function for that (override some method, create some category for NSPredicate)
Thanks in advance.
OK, this is possible, but it's weird. We'll have to build the format string programmatically. Alternatively, we could built it all by creating the individual NSExpression objects, but that'd be a lot more code (albeit likely safer, but whatever).
NSDate *maxDate = ...;
NSArray *arrayOfDates = ...; // an NSArray of NSDate objects
NSMutableArray *dateFormats = [NSMutableArray array];
for (NSDate *date in arrayOfDates) {
NSString *format = [NSString stringWithFormat:#"%f", [date timeIntervalSinceReferenceDate]];
[dateFormats addObject:format];
}
NSString *dateFormatString = [dateFormats componentsJoinedByString:#","];
NSString *format = [NSString stringWithFormat:#"CAST(max({%#}) = %%#, 'NSDate')", dateFormatString];
// format now looks like CAST(max({xxxx.xxxx, nnnn.nnnn, aaaa.aaaa, ....}), 'NSDate') = %#
NSPredicate *datePredicate = [NSPredicate predicateWithFormat:format, maxDate];
The trick here is to use the date's absolute time interval since the reference date as the arguments to the max() function, and then turn the result of that back into a date by using CAST(). More info on how to use the CAST() function with dates can be found in this blog post.
This solutions is realy good, but don't solve my problem.
I got something like this:
NSPredicate* predicate = [NSPredicate predicateWithFormat: condition];
[predicate evaluateWithObject:nil substitutionVariables: currentForm];
And condition can be:
max($widgetWhichReturnDate.result.result,$widgetWhichReturnDate.result)
or
max($widgetWhichReturnInt.result,$widgetWhichReturnInt1.result)
what widget is used here depends from webservice.
So I don't like to use different functions for Date and int (or in the future maybe float, double etc)

How to extract only date from full date (2011-05-15) and store in array in iphone

Full date string 2011-05-15, 2011-05-17, 2011-05-18, 2011-05-20, are comes from server i want to extract only Day value (15,17,18,20..etc) and store it in ur local Array
and show these days(these are Events days) in calendar with red color. how can i do this. Please any one give me idea.
Thanks in Advance :)
The following block should help you
NSMutableArray *arr=[[NSMutableArray alloc] init];
for(NSString *date in [#"2011-05-15, 2011-05-17, 2011-05-18, 2011-05-20" componentsSeperatedByString:#","])
{
NSString *day=[[date componentsSeperatedByString:#"-"] objectAtIndex:2];
[arr addObject:day];
}

Sort items in a UITableView by date

So in my app, I have a UITableView, and in the navigation controller there is a button to add a new item. This than takes you to an add an item screen and when you finish, i use a custom delegate to pass the information from the detail viewController to the main tableViewController. Now that I have the info from delegate, I take the 3 pieces of info and put them in an NSArray in my main Array. Now my question is, how can I sort the detail items by date. I have tried (unsuccessfully) 3 times now and I can't seem to figure it out. The arrays and dictionarys get confusing because they are nested. Any help is greatly appreciated.
The Delegate Method in the tableViewController class:
-(void)finishedAddingFoodItemFromDetail:(NSDate *)date whatWasEaten:(NSString *)whatFood whichMeal:(NSString *)meal{
NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"MMMM d, yyyy"];
NSString *dateString = [[NSMutableString alloc] init];
dateString = [dateFormatter stringFromDate:date];
if (!self.theArray) {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"theArray"]) {
self.theArray = [defaults objectForKey:#"theArray"];
}
else{
self.theArray = [[NSMutableArray alloc] init];
}
}
[self.theArray addObject:[NSArray arrayWithObjects:dateString, meal, whatFood, nil]];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:self.theArray forKey:#"theArray"];
[self.tableView reloadData];
[self dismissModalViewControllerAnimated:YES];
}
This is the file higharchy I was thinking of, but I can't seem to implement it.
/* file higharchy
* - theBigDict //large dictionary holding everything
* - MutableArray by day stored as objects of theBigDict
* - Array of the meals info:
* - Meal type
* - Food
*/
There are several methods on NSMutableArray you can call to sort its contents:
– sortUsingDescriptors:
– sortUsingComparator:
– sortWithOptions:usingComparator:
– sortUsingFunction:context:
– sortUsingSelector:
Since you have an array of complex objects, you will need to write your own function or comparator and call the appropriate sortUsingXxx: method. Do this before you store the array back into NSUserDefaults and before calling reloadData: on your table.
Does this help?
EDIT: Your custom function or comparator will have to pull out the date from the two array elements being compared (passed into your function) and return the appropriate comparison results, e.g. NSOrderedAscending, etc.

How to get an NSDate from an integer passed in as and id?

This is driving me nuts so I hope someone can help an Objective-C noob figure this out. Here's the deal:
I'm developing an iPhone app using Titanium Appcelerator and I'm trying to create an add-on module in XCode that will allow me to send an event to the iPhone calendar. What I'd like to do is to calculate the date and time in terms of seconds since Jan 1, 2001 (GMT) and send it directly to calendar without having to mess with the string-to-date stuff that seems always to return the wrong time. To this point, I've not been able to get the integer into the event date fields, both of which are NSDate types.
Titanium takes arguments from Javascript and compiles it into object code, so I can call my "cal" object like this:
var startDate = 316367923;
var endDate = 316367923;
var results = cal.newEvent(startTime,endTime)
. . . and this is how the "cal" object receives that call:
-(BOOL)newEvent:(id)args {
id startDate = [args objectAtIndex:0];
id endDate = [args objectAtIndex:1];
...
What I'm hoping to do get these integers into the event object:
EKEventStore *eventDB = [[EKEventStore alloc] init];
EKEvent *theEvent = [EKEvent eventWithEventStore:eventDB];
...
theEvent.startDate = [[NSDate alloc] initWithTimeIntervalSinceReferenceDate: (int) startDate];
theEvent.endDate = [[NSDate alloc] initWithTimeIntervalSinceReferenceDate: (int) endDate];
This compiles with no errors but causes my app to bomb nonetheless, so I'm figuring I've got something missing in my understanding. Any idea of where I'm going wrong?
Thanks,
Mark
Quite probably 'args' is an NSArray, hence startDate and endDate are objects, not literals. You probably want to do something like:
theEvent.startDate = [[NSDate alloc] initWithTimeIntervalSinceReferenceDate:[startDate intValue]];
If e.g. startDate is an NSNumber. Otherwise, check out the Titanium docs to find out the type of numbers passed in.
This may not be the cause of your crash, but the initWithTimeIntervalSinceReferenceDate NSDate method is expecting an NSTimeInterval (defined as typedef double NSTimeInterval) not an integer.
i.e.: Its method signature is:
- (id)initWithTimeIntervalSinceReferenceDate:(NSTimeInterval)seconds
I'd bet startDate and endDate are being converted to NSNumber objects instead of ints. Therefore, try the following lines:
theEvent.startDate = [[NSDate alloc] initWithTimeIntervalSinceReferenceDate: (int) [startDate intValue]];
theEvent.endDate = [[NSDate alloc] initWithTimeIntervalSinceReferenceDate: (int) [endDate intValue]];
I doubt that your crash has anything to do with it but, you might be leaking. The lines:
theEvent.startDate = [[NSDate alloc] initWithTimeIntervalSinceReferenceDate: (int) startDate];
theEvent.endDate = [[NSDate alloc] initWithTimeIntervalSinceReferenceDate: (int) endDate];
assign an object with retain count 1, if the setter for startDate and EndDate takes ownership of them (I don't know if java will do that or not so I might be wrong) you must store them in a local variable before assigning them to theEvent, so that you can call release afterwards.
so it would look like this:
NSDate *sDate = [[NSDate alloc] initWithTimeIntervalSinceReferenceDate:[startDate intValue]];
theEvent.startDate = sDate;
[sDate release];

Trouble with Core Data dates

I've got a Core Data model set up, with two entities in a one-to-many relationship (Items, and for each item, there can be multiple ResetDates). I'm pretty confident the model is set up correctly.
I can add new Items, and when doing so, add a new ResetDate (using the current date, with [NSDate date]). I can retrieve and display Items. What I'm having trouble with is retrieving and displaying the ResetDates.
Updated: It works now, thanks very much to the answerers below. Here's the code in question:
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"resetDate" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:&sortDescriptor count:1];
NSMutableArray *sortedResets = [[NSMutableArray alloc] initWithArray:[item.resets allObjects]];
[sortedResets sortUsingDescriptors:sortDescriptors];
NSDate *oldDate = [[sortedResets lastObject] resetDate];
if ( !oldDate ) {
oldDate = [NSDate date];
}
NSInteger numberOfDays = [self timeIntervalWithStartDate:oldDate withEndDate:currentDate]; // This function works fine, when given two NSDate objects
daysSinceLabel.text = [NSString stringWithFormat:#"%d days", numberOfDays];
First, NSArray -objectAtIndex: is not returning nil if you pass it an index that is out of the bounds, it will raise an NSRangeException, when you're not sure about the index, and need to use -objectAtIndex:, you have to call the -count method before to check.
More importantly, an NSArray can't contain a nil value, as nil is not an object.
Then, no, it's not an NSDate object, when you ask item for it's resets relationship (item.resets), you get an NSSet that contain Reset managed objects in return, not NSDate objects, what you want is the resetDate attribute of the returned Reset managed objects, maybe something like this :
// NSArray -lastObject method return nil if the array is empty
// Sending messages to nil is Ok there, so we can call resetDate directly
NSDate *oldDate = [[sortedResets lastObject] resetDate];
if ( !oldDate ) {
oldDate = [NSDate date];
}
Hope that help, and that my English is understandable...
Maybe replacing :
NSDate *oldDate = sortedResets[0];
with :
NSDate *oldDate = [sortedResets objectAtIndex:0];
will help. sortedResets is an NSArray object, not a C array ;)