coredata subquery with multiple conditions / relations - core-data

I have the following model:
how can I get all the PT objects where groupId == '2'?
I have tried several ways, but without success.
With this query, I get one result only:
NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.entity = [NSEntityDescription entityForName:#"Status" inManagedObjectContext:self.managedObjectContext];
request.predicate = [NSPredicate predicateWithFormat:#"group.groupId == %#", [NSNumber numberWithInt:2]];
NSError *error = nil;
NSArray *resultSet = [self.managedObjectContext executeFetchRequest:request error:&error];
[request release];
NSLog(#"array count: %lu", (unsigned long)[resultSet count]);
NSPredicate *thePredicate = [NSPredicate predicateWithFormat:#"hasBeenDeleted == %# AND (ANY hasStatus IN %#)",
[NSNumber numberWithBool:NO],
[NSSet setWithArray:resultSet]];
[self.ptListViewController refreshDataWithPredicate:thePredicate];

You could start with a template "GROUP_BY_GROUP_ID" and add it to the managedObjectModel ...
- (NSManagedObjectModel *)managedObjectModel {
// The managed object model for the application. It is a fatal error for the application not to be able to find and load its model.
if (_managedObjectModel != nil) {
return _managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"GroupdId2" withExtension:#"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
NSFetchRequest *tmpTemplate;
NSEntityDescription *tmpEntity;
NSPredicate *tmpPredicate;
// 1. GROUP_BY_GROUP_ID
tmpEntity = [[_managedObjectModel entitiesByName] objectForKey:#"Group"];
tmpTemplate = [[NSFetchRequest alloc] init];
[tmpTemplate setEntity:tmpEntity];
tmpPredicate = [NSPredicate predicateWithFormat:#"(groupId == $value)"];
[tmpTemplate setPredicate:tmpPredicate];
[_managedObjectModel setFetchRequestTemplate:tmpTemplate forName:#"GROUP_BY_GROUP_ID"];
return _managedObjectModel;
}
Here is the appropriate fetch method:
- (NSArray *)fetchGroupByGroupId:(NSNumber *)value
{
NSError *error = nil;
NSManagedObjectModel *model = _managedObjectModel;
NSDictionary *substitutionDictionary = [NSDictionary dictionaryWithObjectsAndKeys:value, #"value", nil];
NSFetchRequest *fetchRequest = [model fetchRequestFromTemplateWithName:#"GROUP_BY_GROUP_ID" substitutionVariables:substitutionDictionary];
NSArray *results = [_managedObjectContext executeFetchRequest:fetchRequest error:&error];
return results;
}
Now you can start fetching PT entities like this (Xcode lets you generate the NSManagedObject subclasses for all entities):
NSArray *groups=[self fetchGroupByGroupId:#(2)];
NSMutableSet *resultPT=[[NSMutableSet alloc] init];
for (Group *group in groups) {
for (Status *status in group.hasStatus) {
for (PTStatus *ptstatus in status.ptStatus) {
if (ptstatus.targetPT!=nil) {
[resultPT addObject:ptstatus.targetPT];
}
if (ptstatus.pt!=nil) {
[resultPT addObject:ptstatus.pt];
}
}
}
}
In resultPT now you will find all different PT entities "with" groupId == '2'.
You find a XCode 6.1 project here: XCode 6.1 project on Dropbox.
Hope it helps.

I found it!
I had a bug when relating the Status with the Group.
Correct code for achieving:
NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.entity = [NSEntityDescription entityForName:#"PTStatus" inManagedObjectContext:self.managedObjectContext];
request.predicate = [NSPredicate predicateWithFormat:#"ANY status.group.groupId == %#", [NSNumber numberWithInt:2]];
NSError *error = nil;
NSArray *resultSet = [self.managedObjectContext executeFetchRequest:request error:&error];
[request release];
NSLog(#"array count: %lu", (unsigned long)[resultSet count]);
NSPredicate *thePredicate = [NSPredicate predicateWithFormat:#"hasBeenDeleted == %# AND (ANY hasStatus IN %#)",
[NSNumber numberWithBool:NO],
[NSSet setWithArray:resultSet]];
[self.ptListViewController refreshDataWithPredicate:thePredicate];
and [self.ptListViewController refreshDataWithPredicate:thePredicate]; has
- (void)refreshDataWithPredicate:(NSPredicate *)predicate{
self.fetchedResultsController = nil;
[NSFetchedResultsController deleteCacheWithName:#"PTs_Cache"];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.entity = [NSEntityDescription entityForName:#"PT" inManagedObjectContext:self.managedObjectContext];
request.sortDescriptors = [NSArray arrayWithObjects:
[NSSortDescriptor sortDescriptorWithKey:#"requestDate" ascending:NO],
[NSSortDescriptor sortDescriptorWithKey:#"number" ascending:YES],
nil];
request.predicate = predicate;
request.fetchBatchSize = 40;
NSString *sectionNameKeyPathString = #"dateSection_transient";
NSFetchedResultsController *frc = [[NSFetchedResultsController alloc] initWithFetchRequest:request
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:sectionNameKeyPathString
cacheName:#"PTs_Cache"];
[request release];
self.fetchedResultsController = frc;
[frc release];
[self.theTable reloadData];
}

Related

Core Data properties based upon relationships returning NULL

I have a Core Data data model such as
I want to display the Teams.name associated with each Batting object in my UITableViewCell. When I try to access batting.teams.name it returns NULL.
My opening view controller has a string passed in then creates a new viewController with NSPredicate based from Master.nameLast and lists all names matching
and the NSFetchedResultsController which created the above list
#pragma mark - Fetched Results Controller Section
- (NSFetchedResultsController *)fetchedResultsController {
if(_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSManagedObjectContext *context = [self managedObjectContext];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Master" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"debut" ascending:YES];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"nameLast = [c]%#", lastName];
[fetchRequest setPredicate:predicate];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
fetchRequest.sortDescriptors = sortDescriptors;
_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:nil cacheName:nil];
return _fetchedResultsController;
}
My next view controller then lists all Batting properties associated with the selected Master NSManagedObject.
But when I try to access batting.teams.name it returns NULL!!!!! If I NSLog the entity from my delegate they are set but I can't access Teams.name from it's Batting.teams relationship
#pragma mark - Fetched Results Controller Section
- (NSFetchedResultsController *)fetchedResultsController {
if(_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSManagedObjectContext *context = [self managedObjectContext];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Batting" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"yearID" ascending:YES];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"playerID = %# " , selectedMaster.playerID];
[fetchRequest setPredicate:predicate];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
fetchRequest.sortDescriptors = sortDescriptors;
_fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:nil cacheName:nil];
return _fetchedResultsController;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"playerStats" forIndexPath:indexPath];
Batting *batting = [self.fetchedResultsController objectAtIndexPath:indexPath];
NSString *team = batting.teams.name; //NULL NULL NULL
// Configure the cell...
double average = [batting.h doubleValue]/[batting.ab doubleValue];
NSString *averageStr = [[NSString stringWithFormat:#"%.3f", average] substringFromIndex:1];
cell.textLabel.text = [NSString stringWithFormat:#"%# %#", batting.yearID, batting.teams.name];
cell.detailTextLabel.text = [NSString stringWithFormat:#"H: %#, AVG: %#, HR: %#, RBI: %#, SB: %#, R: %#, BB: %#, K: %#",
batting.h, averageStr , batting.hr, batting.rbi, batting.sb, batting.r, batting.bb, batting.so];
cell.detailTextLabel.textColor = [UIColor grayColor];
return cell;
}
returns null for the second argument????????
cell.textLabel.text = [NSString stringWithFormat:#"%# %#", batting.yearID, batting.teams.name];
and this is the Teams entity logged from the AppDelegate
//
// AppDelegate.m
// Baseball Stats
//
// Created by Jason Steindorf on 6/6/15.
// Copyright (c) 2015 Jason Steindorf. All rights reserved.
//
#import "AppDelegate.h"
#import "Master.h"
#import "Teams.h"
#import "Batting.h"
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
NSError *error;
NSString* dataPath_MASTER = [[NSBundle mainBundle] pathForResource:#"master" ofType:#"json"];
NSArray* MASTER = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:dataPath_MASTER]
options:kNilOptions
error:&error];
NSString* dataPath_TEAMS = [[NSBundle mainBundle] pathForResource:#"teams" ofType:#"json"];
NSArray* TEAMS = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:dataPath_TEAMS]
options:kNilOptions
error:&error];
NSString* dataPath_ABC = [[NSBundle mainBundle] pathForResource:#"abc" ofType:#"json"];
NSArray* BATTING_ABC = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:dataPath_ABC]
options:kNilOptions
error:&error];
NSString* dataPath_DEFGH = [[NSBundle mainBundle] pathForResource:#"defgh" ofType:#"json"];
NSArray* BATTING_DEFGH = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:dataPath_DEFGH]
options:kNilOptions
error:&error];
NSString* dataPath_IJKLM = [[NSBundle mainBundle] pathForResource:#"ijklm" ofType:#"json"];
NSArray* BATTING_IJKLM = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:dataPath_IJKLM]
options:kNilOptions
error:&error];
NSString* dataPath_NOPQR = [[NSBundle mainBundle] pathForResource:#"nopqr" ofType:#"json"];
NSArray* BATTING_NOPQR = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:dataPath_NOPQR]
options:kNilOptions
error:&error];
NSString* dataPath_ST = [[NSBundle mainBundle] pathForResource:#"st" ofType:#"json"];
NSArray* BATTING_ST = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:dataPath_ST]
options:kNilOptions
error:&error];
NSString* dataPath_UVWXYZ = [[NSBundle mainBundle] pathForResource:#"uvwxyz" ofType:#"json"];
NSArray* BATTING_UVWXYZ = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:dataPath_UVWXYZ]
options:kNilOptions
error:&error];
// Test listing all Master from the store
NSFetchRequest *fetchRequestMaster = [[NSFetchRequest alloc] init];
NSEntityDescription *entityMaster = [NSEntityDescription entityForName:#"Master" inManagedObjectContext:self.managedObjectContext];
[fetchRequestMaster setEntity:entityMaster];
NSArray *fetchedObjectsMaster = [self.managedObjectContext executeFetchRequest:fetchRequestMaster error:&error];
NSLog(#"Number of records in master.json - %d", (int)[fetchedObjectsMaster count]);
for (id m in MASTER) {
Master *master = [NSEntityDescription insertNewObjectForEntityForName:#"Master"
inManagedObjectContext:self.managedObjectContext];
master.nameFirst = [m objectForKey:#"nameFirst"];
master.nameLast = [m objectForKey:#"nameLast"];
master.debut = [m objectForKey:#"debut"];
master.playerID = [m objectForKey:#"playerID"];
NSError *error;
if (![self.managedObjectContext save:&error]) {
NSLog(#"Whoops, couldn't save: %#", [error localizedDescription]);
}
}
fetchedObjectsMaster = [self.managedObjectContext executeFetchRequest:fetchRequestMaster error:&error];
for (Master *master in fetchedObjectsMaster) {
NSLog(#"first name: %#", master.nameFirst);
NSLog(#"last name: %#", master.nameLast);
NSLog(#"debut: %#", master.debut);
NSLog(#"playerID: %#\n\n", master.playerID);
}
// Test listing all Master from the store
NSFetchRequest *fetchRequestTeams = [[NSFetchRequest alloc] init];
NSEntityDescription *entityTeams = [NSEntityDescription entityForName:#"Teams" inManagedObjectContext:self.managedObjectContext];
[fetchRequestTeams setEntity:entityTeams];
NSArray *fetchedObjectsTeams = [self.managedObjectContext executeFetchRequest:fetchRequestTeams error:&error];
NSLog(#"Number of records in teams.json - %d", (int)[fetchedObjectsTeams count]);
for (id t in TEAMS) {
Teams *team = [NSEntityDescription insertNewObjectForEntityForName:#"Teams"
inManagedObjectContext:self.managedObjectContext];
team.name = [t objectForKey:#"name"];
team.minYearID = [t objectForKey:#"minYearID"];
team.maxYearID = [t objectForKey:#"maxYearID"];
team.teamID = [t objectForKey:#"teamID"];
NSError *error;
if (![self.managedObjectContext save:&error]) {
NSLog(#"Whoops, couldn't save: %#", [error localizedDescription]);
}
}
fetchedObjectsTeams = [self.managedObjectContext executeFetchRequest:fetchRequestTeams error:&error];
for (Teams *team in fetchedObjectsTeams) {
NSLog(#"name: %#", team.name);
NSLog(#"minYearID: %#", team.minYearID);
NSLog(#"maxYearID: %#", team.maxYearID);
NSLog(#"teamID: %#\n\n", team.teamID);
}
NSFetchRequest *fetchRequestBatting = [[NSFetchRequest alloc] init];
NSEntityDescription *entityBatting = [NSEntityDescription entityForName:#"Batting" inManagedObjectContext:self.managedObjectContext];
[fetchRequestBatting setEntity:entityBatting];
NSArray *fetchedObjectsBatting = [self.managedObjectContext executeFetchRequest:fetchRequestBatting error:&error];
NSLog(#"Number of records in battingFiles.json - %d", (int)[fetchedObjectsBatting count]);
for (id b in BATTING_UVWXYZ) {
Batting *batting = [NSEntityDescription insertNewObjectForEntityForName:#"Batting"
inManagedObjectContext:self.managedObjectContext];
batting.playerID = [b objectForKey:#"playerID"];
batting.h = [b objectForKey:#"h"];
batting.ab = [b objectForKey:#"ab"];
batting.hr = [b objectForKey:#"hr"];
batting.rbi = [b objectForKey:#"rbi"];
batting.sb = [b objectForKey:#"sb"];
batting.r = [b objectForKey:#"r"];
batting.bb = [b objectForKey:#"bb"];
batting.so = [b objectForKey:#"so"];
batting.yearID = [b objectForKey:#"yearID"];
batting.teamID = [b objectForKey:#"teamID"];
NSError *error;
if (![self.managedObjectContext save:&error]) {
NSLog(#"Whoops, couldn't save: %#", [error localizedDescription]);
}
}
fetchedObjectsBatting = [self.managedObjectContext executeFetchRequest:fetchRequestBatting error:&error];
for (Batting *b in fetchedObjectsBatting) {
NSLog(#"playerID: %#", b.playerID);
NSLog(#"h: %#", b.h);
NSLog(#"ab: %#", b.ab);
NSLog(#"hr: %#", b.hr);
NSLog(#"rbi: %#", b.rbi);
NSLog(#"sb: %#", b.sb);
NSLog(#"r: %#", b.r);
NSLog(#"bb: %#", b.bb);
NSLog(#"so: %#", b.so);
NSLog(#"yearID: %#", b.yearID);
NSLog(#"teamID: %#\n\n", b.teamID);
}
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
// Saves changes in the application's managed object context before the application terminates.
[self saveContext];
}
#pragma mark - Core Data stack
#synthesize managedObjectContext = _managedObjectContext;
#synthesize managedObjectModel = _managedObjectModel;
#synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
- (NSURL *)applicationDocumentsDirectory {
// The directory the application uses to store the Core Data store file. This code uses a directory named "steindorf.Baseball_Stats" in the application's documents directory.
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
- (NSManagedObjectModel *)managedObjectModel {
// The managed object model for the application. It is a fatal error for the application not to be able to find and load its model.
if (_managedObjectModel != nil) {
return _managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"Baseball_Stats" withExtension:#"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return _managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
// The persistent store coordinator for the application. This implementation creates and return a coordinator, having added the store for the application to it.
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
// Create the coordinator and store
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"Baseball_Stats.sqlite"];
NSLog(#"%#", storeURL);
NSError *error = nil;
NSString *failureReason = #"There was an error creating or loading the application's saved data.";
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
// Report any error we got.
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[NSLocalizedDescriptionKey] = #"Failed to initialize the application's saved data";
dict[NSLocalizedFailureReasonErrorKey] = failureReason;
dict[NSUnderlyingErrorKey] = error;
error = [NSError errorWithDomain:#"YOUR_ERROR_DOMAIN" code:9999 userInfo:dict];
// Replace this with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
return _persistentStoreCoordinator;
}
- (NSManagedObjectContext *)managedObjectContext {
// Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.)
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (!coordinator) {
return nil;
}
_managedObjectContext = [[NSManagedObjectContext alloc] init];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
return _managedObjectContext;
}
#pragma mark - Core Data Saving support
- (void)saveContext {
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
if (managedObjectContext != nil) {
NSError *error = nil;
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
}
#end
In the block below, you need to assign the team to batting.
batting.teams = {your_team_object}
Then you will be able to access the team information. You can create another fetch to Core Data using the teamID to retrieve the team object.
for (id b in BATTING_UVWXYZ) {
Batting *batting = [NSEntityDescription insertNewObjectForEntityForName:#"Batting"
inManagedObjectContext:self.managedObjectContext];
batting.playerID = [b objectForKey:#"playerID"];
batting.h = [b objectForKey:#"h"];
batting.ab = [b objectForKey:#"ab"];
batting.hr = [b objectForKey:#"hr"];
batting.rbi = [b objectForKey:#"rbi"];
batting.sb = [b objectForKey:#"sb"];
batting.r = [b objectForKey:#"r"];
batting.bb = [b objectForKey:#"bb"];
batting.so = [b objectForKey:#"so"];
batting.yearID = [b objectForKey:#"yearID"];
batting.teamID = [b objectForKey:#"teamID"];
NSPredicate *teamIDPredicate = [NSPredicate predicateWithFormat:#"teamID == %#", [b objectForKey:#"teamID"]];
[fetchRequestTeams setPredicate:predicate];
NSArray *fetchedSpecificTeam = [self.managedObjectContext executeFetchRequest:fetchRequestTeams error:&error];
batting.teams= [fetchedSpecificTeam objectAtIndex:0];
NSError *error;
if (![self.managedObjectContext save:&error]) {
NSLog(#"Whoops, couldn't save: %#", [error localizedDescription]);
}
}

iOS Core Data error when updating

I want to update a field in a table. However when I save after fetching and modifying the field, error 1570 is thrown. [Mandatory value is nil].
MyAppDelegate *appdelegate = DELEGATE;
NSManagedObjectContext *context = [appdelegate managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"MyTable" inManagedObjectContext:context];
[request setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(myAttribute_id = %#)",myAttribute.attribute_id];
[request setPredicate:predicate];
NSError *error = nil;
NSArray *results = [context executeFetchRequest:request error:&error];
for (myAttribute *obj in results) {
NSLog(#"myAttribute_id : %#",myAttribute.attribute_id);
[obj setValue:myAttribute.attribute2_id forKey:#"attribute2_id"];
[context save:&error];
NSLog(#"save error : %#",error);
}
Here I get an error. Whereas all mandatory fields are already set.

Serious issue in parsing xml and storing details using coredata

I am using google weather api to get weather information,I am using coredata to store information.I am running into troble.I am getting results on labels and UImageview to store information using coredata.My code is posted below
-(IBAction)sBarpress:(id)sender
{
NSString *urlString = [NSString stringWithFormat:#"http://www.google.co.uk/ig/api?weather=%#",sBar.text];
NSURL *url = [NSURL URLWithString:urlString];
NSLog(#"buttonpress");
WeatherXMLParser *delegate = [[WeatherXMLParser alloc] init];
NSXMLParser *locationParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
[locationParser setDelegate:delegate];
[locationParser setShouldResolveExternalEntities:YES];
[locationParser parse];
/*
NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.entity = [NSEntityDescription entityForName:#"Weather" inManagedObjectContext:context];
request.predicate = [NSPredicate predicateWithFormat:#"uniqueId = %#", [Data objectForKey:#"id"]];
NSError *error = nil;
NSManagedContext *returnedData = [[context executeFetchRequest:request error:&error] lastObject];
[request release];
[NSEntityDescription insertNewObjectForEntityForName:#"condition" inManagedObjectContext:context];
MODEL_OBJECT.uniqueId = [Data objectForKey:#"id"];
MODEL_OBJECT.title = [Data objectForKey:#"title"];
*/
for (WeatherCondition *condition in delegate.forecastConditions) {
NSLog(#"description is %#", condition.description);
hightemplabel.text=condition.description;
}
for (WeatherCondition *condition in delegate.forecastConditions) {
NSLog(#"description is %#", condition.icon);
NSData *mydata=[[NSData alloc]initWithContentsOfURL:[NSURL URLWithString:#"http://www.google.co.uk/ig/images/weather/partly_cloudy.gif"]];
conditionsImageView.image = [[UIImage alloc] initWithData:mydata ];
}
for (WeatherCondition *condition in delegate.forecastConditions) {
NSLog(#"description is %#", condition.icon);
NSData *mydata=[[NSData alloc]initWithContentsOfURL:[NSURL URLWithString:#"http://www.google.co.uk/ig/images/weather/thunderstorm.gif"]];
forecastimage.image = [[UIImage alloc] initWithData:mydata ];
}
for (WeatherCondition *condition in delegate.forecastConditions) {
NSLog(#"description is %#", condition.description);
humiditylabel.text=condition.description;
}
[self fetchRecords];
[locationParser release];
[delegate release];
// NSDictionary *airport = [responseString JSso ];
// displaybox.text=[airport objectForKey:#"location"];
/*
NSURL *url=[NSURL URLWithString:#"http://airportcode.riobard.com/airport/%#?fmt=json"];http://free.worldweatheronline.com/feed/weather.ashx?q=omaha%2c+ne,united+states&format=json&num_of_days=5&key=691607e82d192404111506 &format=jason
//NSURL *url = [NSURL URLWithString:urlString];
NSData *data = [response dataUsingEncoding:NSUTF8StringEncoding];
WeatherParser *locationParser = [[WeatherParser alloc] init];
[locationParser parseData:data];
label.text = locationParser.location;
urlString = [NSString stringWithFormat:#"http://free.worldweatheronline.com/feed/weather.ashx?q=%#&format=json&num_of_days=5&key=691607e82d192404111506",locationParser.location];
url = [NSURL URLWithString:urlString];
NSLog(#"area coming");
[response release];
response = [[NSString alloc] initWithContentsOfURL:url];
data = [response dataUsingEncoding:NSUTF8StringEncoding];
WeatherParser *weatherParser = [[WeatherParser alloc] init];
[weatherParser parseData:data];
[locationParser release];
[weatherParser release];
*/
}
- (void)fetchRecords {
// Define our table/entity to use
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Weather" inManagedObjectContext:managedObjectContext];
NSLog(#" entity is %#",entity);
// Setup the fetch request
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entity];
// If a predicate was passed, pass it to the query
if(predicate != nil)
{
[request setPredicate:predicate];
}
// Define how we will sort the records
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"condition" ascending:NO];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
[request setSortDescriptors:sortDescriptors];
[sortDescriptor release];
// Fetch the records and handle an error
NSError *error;
NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
if (!mutableFetchResults) {
// Handle the error.
// This is a serious error and should advise the user to restart the application
}
// Save our fetched data to an array
[self setEventArray: mutableFetchResults];
[mutableFetchResults release];
[request release];
}
You didnt really describe what the trouble is, but I can see some possible performance issues in your code ...
You are looping multiple times:
for (WeatherCondition *condition in delegate.forecastConditions) {
NSLog(#"description is %#", condition.description);
hightemplabel.text=condition.description;
}
for (WeatherCondition *condition in delegate.forecastConditions) {
NSLog(#"description is %#", condition.icon);
NSData *mydata=[[NSData alloc]initWithContentsOfURL:[NSURL URLWithString:#"http://www.google.co.uk/ig/images/weather/partly_cloudy.gif"]];
conditionsImageView.image = [[UIImage alloc] initWithData:mydata ];
}
refactor these loops into one loop through the results:
for (WeatherCondition *condition in delegate.forecastConditions) {
NSLog(#"description is %#", condition.description);
hightemplabel.text=condition.description;
NSLog(#"icon is %#", condition.icon);
NSData *mydata=[[NSData alloc]initWithContentsOfURL:[NSURL URLWithString:#"http://www.google.co.uk/ig/images/weather/partly_cloudy.gif"]];
conditionsImageView.image = [[UIImage alloc] initWithData:mydata ];
}

Printing Core Data

I'm working on a program and I have created a fetch request to grab the data that I need to print. I'm able to log information like this:
2010-10-03 16:57:10.362 lzshow7.2[2537:10b] <NSManagedObject: 0x2ca120> (entity: Song; id: 0x2afcb0 <x-coredata://CF5A85CE-BE0F-4ADC-979A-7F4214A8FB19/Song/p9> ; data: {
cueName = Freedom;
cueNo = 014;
cueNotes = nil;
songToInstrument = "<relationship fault: 0x2b1800 'songToInstrument'>";
})
How do I seperate the properties like cueName, cueNo, cueNotes out to be printed?
Here is the fetch request:
//Managed object context???
NSLog(#"setting Managed object stuff");
NSManagedObjectContext *context=[[[NSDocumentController sharedDocumentController] currentDocument] managedObjectContext];
NSLog(#"Second line of Managed object stuff");
//fetch request:
NSLog(#"Starting to fetch:");
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Song" inManagedObjectContext:context];
[request setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"cueNo" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
[sortDescriptors release];
[sortDescriptor release];
NSError *error;
NSMutableArray *mutableFetchResults = [[context executeFetchRequest:request error:&error] mutableCopy];
for (id obj in mutableFetchResults)
NSLog(#"%#", obj);
NSLog(#"finished looping");
//Error handling
if (mutableFetchResults == nil) {
// Handle the error.
}
//[self setEventsArray:mutableFetchResults];
[mutableFetchResults release];
[request release];
}
Any help would be greatly appreciated.
Thank you,
Loren
You use basically the opposite of how you stored the values in your managedObject
NSString *name = [song valueForKey:#"cueName"];
NSNumber *number = [song valueForKey:#"cueNo"];
NSString *notes = [song valueForKey:#"cueNotes"];
...
NSLog(#"%# %# %#", name, number, notes);
if you've created a custom Class of your entity you could add this method:
- (NSString *)description {
NSString *name = [song valueForKey:#"cueName"];
NSNumber *number = [song valueForKey:#"cueNo"];
NSString *notes = [song valueForKey:#"cueNotes"];
...
NSString *returnString = [NSString stringWithFormat:#"%# %# %#", name, number, notes];
return returnString;
}
With this method you can just use NSLog(#"%#", object); to get a nice formatted output

NSPredicate problem with fetchedResultsController

Please help! I've been trying to figure this out for way too long.
I can't seem to use an NSPredicate in my fetchedResultsController method:
- (NSFetchedResultsController *)fetchedResultsController {
if (fetchedResultsController != nil) return fetchedResultsController;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Tweet" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat: #"column == 0"];
[fetchRequest setPredicate:predicate];
[fetchRequest setReturnsObjectsAsFaults:NO];
[fetchRequest setFetchBatchSize:20];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"created_at" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:#"Root"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
[aFetchedResultsController release];
[fetchRequest release];
[sortDescriptor release];
[sortDescriptors release];
return fetchedResultsController; }
Yet, in another method, where I simply check to see if an object exists, the predicate works like a charm:
- (BOOL)findObjectWithKey:(NSString *)key andValue:(NSString *)value sortBy:(NSString *)sort {
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Tweet" inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat: #"%K == %#", key, value];
[request setPredicate:predicate];
[request setReturnsObjectsAsFaults:NO];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sort ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:#"Root"];
aFetchedResultsController.delegate = self;
NSError *error = nil;
NSArray *result = [managedObjectContext executeFetchRequest:request error:&error];
[aFetchedResultsController release];
[request release];
[sortDescriptor release];
[sortDescriptors release];
if ((result != nil) && ([result count]) && (error == nil)) {
return TRUE;
} else {
return FALSE;
}}
What am I doing wrong? Thanks in advance!
Assuming your "column" attribute is a number, you should compare it to an NSNumber object like this:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"column == %#",[NSNumber numberWithInteger:0]];
Since column is a property on the entity then your predicate logic is fine. What results are you seeing that indicate the predicate is not working?

Resources