Core Data Storing Unnecessary Data - iphone

I am trying to parse google weather API. I am using nsxml parser to get dates, weather etc from the api and then I store them in Core Data.
What I am trying to do is extract dates up from the parser, match them with the current date and then store only as many information we need to store.
Say, today's date is 08/09/2011 and a date from the parse matches. I wish to store only 2 information from the parser into Core Data. I am trying to store only those dates but I am getting all 4 information to be stored into Core Data.
If I give 08/11/2011, I should be only getting 3 days of information not 4. But I am unable to do that. I am posting my sample code. I am using testcase to check my application.
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict
{
if ([#"forecast_date" isEqualToString:elementName])
{
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"yyyy-MM-dd"];
startDate = [formatter dateFromString:[attributeDict objectForKey:#"data"]];
[formatter release];
}
else if ([#"forecast_conditions" isEqualToString:elementName])
{
isParsingForecast = YES;
isParsingInformation = NO;
isParsingCurrent = NO;
newdate=[startDate addTimeInterval:60*60*24*[forecastConditions count]];
NSMutableDictionary *fields = [[NSMutableDictionary alloc] init];
[fields setObject:newdate forKey:#"date"];
[fields setObject:city forKey:#"city"];
[fields setObject:state forKey:#"state"];
[fields setObject:country forKey:#"country"];
[fields setObject:startDate forKey:#"startdate"];
//[fields setObject: forKey:<#(id)#>]
[forecastConditions addObject:fields];
[fields release];
}
else if (isParsingForecast) {
NSMutableDictionary *fields = [forecastConditions lastObject];
NSLog(#"dic is : %# \n\n",fields);
[fields setObject:[attributeDict objectForKey:#"data"] forKey:elementName];
}
}
Posted my whole code here
http://www.iphonedevsdk.com/forum/iphone-sdk-development/87475-coredata-storing-more-values-than-what-required-store-database.html#post363100

The code at the link is unformatted and very hard to read. However, I did find one major problem.
This predicate will always fail:
predicate = [NSPredicate predicateWithFormat:
#"city == %# and state == %# and country == %# and date==%# and date==%#", city, state, country,startDate,endDate];
... if startDate and endDate values are not identical. You can't test the same key name against two different values and ever expect it to pass.
Since, a fetch returns only those objects who pass the predicate, a predicate that always fails always returns zero objects.
Since you apparently are using the predicate to find existing objects that already contain the parsed data, the always failing predicate means your code always thinks it needs to create a new managed object. That is why your object graph fills up with objects with duplicate values.

Related

NSArray gives NSZombie error

I am trying to pass a single array object (that is a nsdictionary of several values) back to my main view.
basicly when I set the view up I parse some xml into an array of dictionaries. I then set up my tableview with one of the values inside the NSdictionary, this value is also used to set up the alphabetical scroller and section titles. (this is done in a method I created)
At the end of that method I call [self.tableView reloadData]; every thing loads up perfectly and everything displays fine.
Now what I am trying to do is set it up so that when a cell is selected, I check the value inside the cell.textlabel and use that as a predicate to check against my array of dictionaries once It finds the corresponding entry I want to pass that dictionary up to the main view with a delegate I have made.
however I am getting a error, that I think might be happening due to my reloadData.. but am not sure.
This is what my predicate looks like.
NSPredicate *pred = [NSPredicate predicateWithFormat:#"%K like %#",#"MANUFACTURER",cell.textLabel.text];
NSArray *filter = [myDataArray filteredArrayUsingPredicate:pred]; //error happens here
//check to see if the value is the correct one
NSLog(#"My Filtered array = %#", filter);
//once problem has been found set up the delegate here.
and this is the error message I receive.
2011-10-31 10:43:57.333 code[5812:207] *** -[__NSArrayM filteredArrayUsingPredicate:]: message sent to deallocated instance 0x6874210
myDataArray is created in the NSXMLParser delegates as listed below.
//.h
NSMutableArray *myDataArray;
}
#property (nonatomic, retain) NSMutableArray *myDataArray;
//.m
#pragma mark - Parsing lifecycle
- (void)startTheParsingProcess:(NSData *)parserData
{
//myDataArray = [NSMutableArray arrayWithCapacity:8]; // not even sure if this is needed as its declared later on.
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:parserData]; //parserData passed to NSXMLParser delegate which starts the parsing process
[parser setDelegate:self];
[parser parse]; // starts the event-driven parsing operation.
[parser release];
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
if([elementName isEqualToString:#"Row"])
{
manufactureMutableDictionary = [[NSMutableDictionary alloc] initWithDictionary:attributeDict];
}
if([elementName isEqualToString:#"Rows"])
{
myDataArray = [NSMutableArray arrayWithCapacity:8];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if([elementName isEqualToString:#"Row"])
{
[myDataArray addObject:manufactureMutableDictionary];
}
[manufactureMutableDictionary release];
manufactureMutableDictionary = nil;
}
Any help would be greatly appreciated, also do you think I am going about passing all the values of the dictionary the right way?
You are using an autoreleased array
myDataArray = [NSMutableArray arrayWithCapacity:8];
You have properties set up so use them e.g.
self.myDataArray = [NSMutableArray arrayWithCapacity:8];
or even better
NSMutableArray *tmpMyDataArray = [[NSMutableArray alloc] initWithCapacity:8];
self.myDataArray = tmpMyDataArray;
[tmpMyDataArray release]; tmpMyDataArray = nil;

how to match nsxml dates from parser and get only the required dates

I am working on an nsxml parser and I have some issues.I am using nsxml parser to parse dates out.I want to get information of only 2 days .not all 4 from google weather api.How can I do it?
NSMutableArray *array=[NSMutableArray arrayWithObjects:startDate,endDate,Nil];
for (NSDate *date in array)
{
if([date isEqualToDate:dd])
{
NSManagedObject *allnew = Nil;
NSManagedObjectContext *allone=[self managedObjectContext];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Weather" inManagedObjectContext:allone];
NSLog(#" The NEW ENTITY IS ALLOCATED AS entity is %#",entity);
WeatherXMLParser *delegate = [[WeatherXMLParser alloc] initWithCity:city state:state country:country];
NSXMLParser *locationParser = [[NSXMLParser alloc] initWithContentsOfURL:delegate.url];
[locationParser setDelegate:delegate];
[locationParser setShouldResolveExternalEntities:YES];
[locationParser parse];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entity];
predicate = [NSPredicate predicateWithFormat:
#"city == %# and state == %# and country == %# and date==%# and date==%#", city, state, country,startDate,endDate];
[request setPredicate:predicate];
NSError *err;
NSUInteger count = [allone countForFetchRequest:request error:&err];
NSLog(#" minimum salary is %#",predicate);
// If a predicate was passed, pass it to the query
if(predicate !=NULL){
[self deleteobject];
}
Weather *weather = (Weather *)[NSEntityDescription insertNewObjectForEntityForName:#"Weather"
inManagedObjectContext:self.managedObjectContext];
weather.date = [fields objectForKey:#"date"];
weather.high =[fields objectForKey:#"high"];
weather.low = [fields objectForKey:#"low"];
weather.city =[fields objectForKey:#"city"];
weather.state =[fields objectForKey:#"state"];
weather.country =[fields objectForKey:#"country"];
NSString*icon=[fields objectForKey:#"icon"];
NSString *all=[icon lastPathComponent];
weather.condition = all;
[self saveContext];
}
I'm not familiar with how your XML file is organized but I assume the problem is that there are 4+ nodes with the same name, of which you only want 2. When I ran into a similar situation I set a flag for myself after the last node that I wanted, so I never read anything else.
In your specific case, create a counter for the number of days that you have read, when you are parsing check to make sure that the node name is "date" (or whatever you are currently doing now to trigger reading the information) and also that your counter is less than 2. Just be sure that you reset your counter every time you invoke your weather update.
Edit for some sample code:
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
if ([elementName isEqualToString:#"Day"] && daysRead < 2) {
if ([[attributeDict objectForKey:#"high"] integerValue] > 0) {
//Store store this value
}
if ([[attributeDict objectForKey:#"low"] integerValue] > 0) {
//Store this value
}
}
}
This is a piece of my parser, I've kind of rewritten it for you. The part that interests you is the variable 'daysRead'. I would recommend using something like this to keep track of how many days you have already read and stored. If you have more than two, simply don't parse and of the remaining days. Don't forget to increment this after finishing each parsed element as well.
Hope this helps!
-Karoly

Parse Nested XML Objective C - NSXMLParser

All,
I have XML in the following format:
<linked-list>
<Description>
<desc></desc>
<IP></IP>
</Description>
</linked-list>
This XML statement could have an infinite number of <Description></Description> inside of the <linked-list></linked-list>.
How should I parse this using NSXMLParser? My current code is as follows, but it parses incorrectly.
#implementation XMLParser
#synthesize response;
- (XMLParser *) initXMLParser
{
self = [super init];
// init dictionary of response data
response = [[NSMutableDictionary alloc] init];
return self;
}
//Gets Start Element of SessionData
- (void)parser:(NSXMLParser *)parser
didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict
{
if ([elementName isEqualToString:#"linked-list"])
{
NSLog(#"Found linked-list in the return XML! Continuing...");
//response is a NSMutableArray instance variable
//THIS SHOULD NEVER NEED TO BE USED
if (!response)//if array is empty, it makes it!
{
NSLog(#"Dictionary is empty for some reason, creating...");
response = [[NSMutableDictionary alloc] init];
}
//END: THIS SHOULD NEVER BE USED
return;
}
else
{
currentElementName = elementName;
NSLog(#"Current Element Name = %#", currentElementName);
return;
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if (!currentElementValue) {
// init the ad hoc string with the value
currentElementValue = [[NSMutableString alloc] initWithString:string];
} else {
[currentElementValue setString:string];
NSLog(#"Processing value for : %#", string);
}
}
//Gets End Element of linked-list
- (void)parser:(NSXMLParser *)parser
didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName {
if ([elementName isEqualToString:#"linked-list"])
{
// We reached the end of the XML document
// dumps dictionary into log
NSLog(#"Dump:%#", [response description]);
return;
}
else
{
//Adds key and object to dictionary
[response setObject:currentElementValue forKey:currentElementName];
NSLog(#"Set values, going around again... brb.");
}
currentElementValue = nil;
currentElementName = nil;
}
#end
Some observations:
An infinite number of WHAT inside of the WHAT?
Assuming there can be more than one Description element, the outer data structure in which you store the contents must be a NSMutableArray, not a dictionary. You then use one mutable dictionary per Description element.
Consequently, in didStartElement:, check if the element name is #"Description" and if so, create a new NSMutableDictionary instance that you store in an ivar.
In foundCharacters:, you always have to append the new characters to the existing currentElementValue because the method can be called multiple times for each element's contents. I see many people do this wrong despite the fact that Apple's sample code clearly demonstrates the correct way.
In didEndElement:, do this:
If the element name is #"desc" or #"IP", assign currentElementValue to the corresponding key in your current mutable dictionary. Don't forget to release currentElementValue before you set it to nil. You currently have a memory leak in your code because you're not doing that.
If the element name is #"Description", add the current mutable dictionary to the mutable array. Release the dictionary and set the ivar to nil. A new dictionary will be created the next time you encounter a #"Description" element in didStartElement:.
If the element name is #"linked-list", the mutable array will contain all the dictionaries and you're done.

What should the return value of a JSON GET or POST look like?

I'm new to JSON and just starting to wrap my head around it's functionality.
I'm trying to see if I can get print some data from some JSON methods. I've been alternating between the first one and the one that is commented out. The ideas is to see if I can get anything printing:
id newConnection = [scAPI performMethod:#"GET" onResource:#"me/connections.json" withParameters:nil context:nil userInfo:nil];
// id newConnection = [scAPI performMethod:#"POST"
// onResource:#"connections"
// withParameters:[NSDictionary dictionaryWithObjectsAndKeys:
// #"facebook_profile", #"service",
// #"imc://connection", #"redirect_uri",
// #"touch", #"display", //optional, forces services to use the mobile auth page if available
// nil]
// context:nil
// userInfo:nil];
NSLog(#"newConnection %#", newConnection);
NSLog(#"Is of type: %#", [newConnection class]);
NSDictionary *dict = [newConnection objectFromJSONString];
for (id key in dict) {
NSLog(#"key: %#, value: %#", key, [dict objectForKey:key]);
}
The above code doesn't err and I get logs such as:
Does this look right? How do I properly use these JSON methods to get a dictionary of values?
EDIT 1
To be clear I'm using JSONKit :)
I would personally recommend using the SBJSON library. Getting a dictionary with it is straightforward.
Get a response back from a connection, and then use the following code (where response is an NSString containing the response from the server):
SBJsonParser *parser = [[SBJsonParser alloc] init];
NSArray *returnData = [parser objectWithString:[response stringByReplacingOccurrencesOfString:#"\\\\" withString:#"\\"]];
[parser release];
NSDictionary *returnDict = (NSDictionary *)returnData;
This is unrelated, but for examining JSON data, I would also recommend Online JSON Viewer. You can paste in your JSON strings and view it with a collapsable array structure. Very convenient.

XMLParsing problem

I display List of date's on my table view....
based on the date's.. i need to search location. and title
"with the help of url".
example
String *url=#"http://compliantbox.com/party_temperature/djsearch.php?date=?"
for the selected date.
i appended the date value to the string url.
So i need to parse again same xml parser. with date search.
<root>
<event title="event_title"location="new york"date="12/01/2011"/>
<event title="event_title2"location="california"date="13/01/2011"/>
<event title="event_title3"location="new york"date="14/01/2011"/>
</root>
here my array get's Re-Initialization.
so i get conflict. when displaying data....
I need to not re-Initialization my array again. and again...
I need to initialize my array only once in entire application.
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict{
if ([elementName isEqualToString:#"root"]){
dateListArray=[[NSMutableArray alloc] init];
}
}
I Hope you people understand my problem.
Please help me out .
#Thanks to All.
One way that you should trying here,
if([dateListArray count] > 0)
{
[dateListArray removeAllObjects];
[dateListArray release];
}
dateListArray=[[NSMutableArray alloc] init];
And other way you should also be trying,
dateListArray=[[NSMutableArray alloc] init];
above statement write down in -(void)viewDidLoad event and
if([dateListArray count] > 0)
{
[dateListArray removeAllObjects];
}
above write down in your required function.
I guess:
NSMutableArray:-removeAllObjects
may help~