how to know when to release string for iphone - iphone

i have this
NSXMLParser *xmlParserf = [[NSXMLParser alloc] initWithContentsOfURL:url];
// NSLog(#"URL%#",urlf);
//Initialize the delegate.
XMLParser *parserf = [[XMLParser alloc] initXMLParser];
[xmlParserf setDelegate:parserf];
//Start parsing the XML file.
BOOL successs = [xmlParserf parse];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSLog(#" this xml is %d",[xmlParserf retainCount]);// getting error
NSLog(#" this paaat is %d",[parserf retainCount]);// getting error
if(successs)
{
NSLog(#"ZONE IS PARSED");
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
else
{
NSLog(#"NOT PARSED!!!");
}
//[xmlParserf release]; not working
//[parserf release];
now i dont know when to release those objects these are running in some threads

everytime you alloc (or copy), you must either release or autorelease.
In this case:
NSXMLParser *xmlParserf = [[[NSXMLParser alloc] initWithContentsOfURL:url] autorelease];
and
XMLParser *parserf = [[[XMLParser alloc] initXMLParser] autorelease];
It means that you keep it in memory at least until the end of the current function. If other objects hang on to it (i.e. retain it) then the objects stay in memory, until they are released (by those other objects).

Related

how parse value of array of one class to other and other to another?

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 1 && indexPath.row == 0) {
NSString *requestString = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/directions/xml?origin=%#&destination=%#,OK&sensor=false",startField.text,endField.text];
NSURL *url = [[NSURL alloc] initWithString:requestString];
NSData *tempData =[[NSData alloc] initWithContentsOfURL:url];
NSString *Str = [[NSString alloc] initWithData:tempData encoding:NSUTF8StringEncoding];
NSLog(#"%#",Str);
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
//Initialize the delegate.
xml1 *parser = [[xml1 alloc] init];
//Set delegate
[xmlParser setDelegate:parser];
//Start parsing the XML file.
BOOL success = [xmlParser parse];
if(success){
NSLog(#"No Errors");
arySteps=[[NSMutableArray alloc]init];
arySteps=[parser.ListofSteps1 mutableCopy];
}
else
NSLog(#"Error Error Error!!!");
controller.arayStep=[[NSMutableArray alloc]init];
controller.arayStep=[parser.ListofSteps1 copy];
controller= [[TableView alloc] initWithNibName:#"TableView" bundle:nil];
[self.navigationController pushViewController:controller animated:YES];
[controller release];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
}
In above code i have parsed XML data. In XML-parser file i have store objects in array that is ListofSteps1. Now i access in root-view controller class which is shown in above code. So in root-view class ListofSteps1 assign value to array of root-view controller. Now i want to assign value of array of root-view controller to next view's array which is also maintain in above code but array of next view is not getting value. What is problem in this code so it not getting value?
There are a couple of things wrong with your code above. You alloc and init a fresh array only to write over it on two separate occasions in your method implementation:
arySteps=[[NSMutableArray alloc]init]; // This line serves absolutely no purpose
arySteps=[parser.ListofSteps1 mutableCopy]; // This line is sufficient on its own
Calling accessor methods on an null pointer will do you absolutely no good. You need to instantiate the object before you attempt to set its properties:
controller= [[TableView alloc] initWithNibName:#"TableView" bundle:nil];
controller.arayStep=[parser.ListofSteps1 copy];
These mistakes are very basic and indicate that you need to work on the fundamentals before you can get too much further. I would suggest that you pick up a good book on Objective-C - for example, Programming in Objective-C by Stephen Kochan - and read it thoroughly. A solid understanding of the core concepts will serve you well going forward.

fetch JSON data asynchronously

I want to fetch JSON data asynchronously. The data is set up in a way that one request will bring only 8 records. I need to send the requests repeatedly until the response becomes empty or returns less than 8 records.
Currently, I have these methods in myviewcontroller.m class:
(void)myCallback:(id)sender {
MyDataRequest *objMyDataRequest = [[[MyDataRequest alloc] init] autorelease];
objMyDataRequest.myRequiredVariableToGetAuthTokenDataResponse = classOfMyCallBack.someVariable;
// Initiate getAuthToken request
[objWishListRequest initiateGetAuthTokenRequest:self requestSelector:#selector(getAuthTokenDataResponse:)];
}
Now here is the definition of getAuthTokenDataResponse:
(void) getAuthTokenDataResponse:(NSData *)data {
NSString *stringResponse = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
SBJsonParser *parser=[[SBJsonParser alloc]init];
NSDictionary *objDictionaryForStringResponse = [parser objectWithString:stringResponse];
[stringResponse release];
[parser release];
MyListRequest *objMyListRequest = [[[MyListRequest alloc] init] autorelease];
objMyListRequest.myRequiredValueToGetMyDataResponse = [objDictionaryForStringResponse objectForKey:#"Data"];
// Initiate GetMyDataResponse request
[objMyListRequest initiateGetMyDataRequest:self requestSelector:#selector(getMyDataResponse:)];
}
(void) getMyDataResponse:(NSData *)data {
NSString *stringResponse = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
SBJsonParser *parser=[[SBJsonParser alloc]init];
NSDictionary *objGetMyDataRootDictionary = [parser objectWithString:stringResponse];
[stringResponse release];
[parser release];
NSDictionary *dataElements=[objGetMyDataRootDictionary objectForKey:#"Data"];
Wish *objMyData;
for (NSDictionary* objGetMyDataRootDictionary in dataElements) {
objMyData = [[Wish alloc]init];
//add different elements from dataElements into member variables of object objWish
[self.myDataArray addObject:objMyData];
[objMyData release];
}
[self.myDataTableView reloadData];
}
This method lies in MyDataRequest class:
(void)initiateGetMyDataRequest:(id)requestDelegate requestSelector:(SEL)requestSelector{
// Set the delegate and selector
self.delegate = requestDelegate;
self.callback = requestSelector;
NSString* unescapedUrlString = [NSString stringWithFormat:#"http://test.mytesturl.com/core.svc/alldata/My/get/All/?token=%#&search=&page=1",myRequiredtokenparameter];
[self request:url];
}
I need to send multiple requests to the same url (with different parameter value i.e. value of page number) to fetch the results. How may I achieve it given the above scenario? The calls must be asynchronous.
How should I make the actual flow between all these calls? How may I get the data of "all the pages" asynchronously?
I think you are looking for a operation queue. I use ASIHTTPRequests in my apps and they work.
If you want to use this library, here's the link how to use it: Show UIActivityIndicatorView when loading NSString from Web

Memory allocation in detached NSThread to load an NSDictionary in background?

I am trying to launch a background thread to retrieve XML data from a web service. I developed it synchronously - without threads, so I know that part works. Now I am ready to have a non-blocking service by spawning a thread to wait for the response and parse.
I created an NSAutoreleasePool inside the thread and release it at the end of the parsing. The code to spawn and the thread are as follows:
Spawn from main-loop code:
.
.
[NSThread detachNewThreadSelector:#selector(spawnRequestThread:)
toTarget:self withObject:url];
.
.
Thread (inside 'self'):
-(void) spawnRequestThread: (NSURL*) url {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
parser = [[NSXMLParser alloc] initWithContentsOfURL:url];
[self parseContentsOfResponse];
[parser release];
[pool release];
}
The method parseContentsOfResponse fills an NSMutableDictionary with the parsed document contents. I would like to avoid moving the data around a lot and allocate it back in the main-loop that spawned the thread rather than making a copy. First, is that possible, and if not, can I simply pass in an allocated pointer from the main thread and allocate with 'dictionaryWithDictionary' method? That just seems so inefficient.
parseContentsOfResponse
-(void)parseContentsOfResponse {
[parser setDelegate:self];
[parser setShouldProcessNamespaces:YES];
[parser setShouldReportNamespacePrefixes:YES];
[parser parse];
NSError *parseError = [parser parserError];
if (parseError) {
NSLog(#"%#", parseError);
NSLog(#"publicID: %#", [parser publicID]);
NSLog(#"systemID: %#", [parser systemID]);
NSLog(#"line:%d column:%d", [parser lineNumber], [parser columnNumber]);
}
ready = YES;
}
First parse section
Each section creates element strings when its elementStart is signaled. The elementEnd will add the object to the dictionary and release the element. The remaining details are redundant and I think the point to note is that the allocations are not directed at an NSZone, therefore they should be residing in the thread's memory pool.
- (void)parserDidStartDocument:(NSXMLParser *)parser {
NSLog(#"%s", __FUNCTION__);
currentChars = [NSMutableString stringWithString:#""];
elementQuestion = [NSMutableString stringWithString:#""];
elementAnswer = [NSMutableString stringWithString:#""];
elementKeyword = [NSMutableString stringWithString:#""];
}
The simplest thing to do would be to create the dictionary in the separate thread, then set it as a property on the main thread, like so:
- (void)spawnRequestThread: (NSURL*) url {
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
//do stuff with dict
[self performSelectorOnMainThread:#selector(doneWithThread:) withObject:dict waitUntilDone:NO];
}
- (void)doneWithThread:(NSDictionary *)theDict {
self.dict = theDict; //retaining property, can be an NSDictionary
}
Do you need to change the contents of the dictionary over time? If so, allocating on the main thread and changing the contents in the other thread is possible, but you have to worry about thread-safety issues--NSMutableDictionary isn't thread-safe, so you'd have to use an atomic property and locks:
//.h
#property (retain) NSMutableDictionary *dict; //don't use "nonatomic" keyword
#property (retain) NSLock *dictLock;
//.m
- (id) init {
//blah blah
dict = [[NSMutableDictionary alloc] init];
dictLock = [[NSLock alloc] init];
return self;
}
- (void)spawnRequestThread: (NSURL*) url {
//whenever you have to update the dictionary
[self.dictLock lock];
[self.dict setValue:foo forKey:bar];
[self.dictLock unlock];
}
Locking is quite expensive and inefficient in any case, so I'd tend to prefer the first method (I'm not sure which is more expensive, exactly, but the first is simpler and avoids thread-safety issues).
Also, looking at your code, it looks like your NSXMLParser is an ivar which you directly access. This is a bad idea, since NSXMLParser isn't thread-safe--I would recommend implementing it as a local variable instead. If you do need it as an ivar, use an atomic property and locks and only access it through accessors.

Stop NSXMLParser Instance from Causing _NSAutoreleaseNoPool

In my iPhone application, I have an instance of NSXMLParser that is set to a custom delegate to read the XML. This is then moved into its own thread so it can update the data in the background. However, ever since I have done this, it has been giving me a lot of _NSAutoreleaseNoPool warnings in the console. I have tried to add a NSAutoreleasePool to each of my delegate classes, however, this hasn't seemed to solve the problem. I have included my method of creating the NSXMLParser in case that is at fault.
NSURL *url = [[NSURL alloc] initWithString:#"http://www.mywebsite.com/xmlsource.xml"];
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
CustomXMLParser *parser = [[CustomXMLParser alloc] init];
parser.managedObjectContext = self.managedObjectContext;
parser = [parser initXMLParser];
[xmlParser setDelegate:parser];
[NSThread detachNewThreadSelector:#selector(parse) toTarget:xmlParser withObject:nil];
If anyone has any ideas to get rid of this problem, I would really appreciate it.
Thanks.
In objective-c each thread needs its own NSAutorelease pool to handle autoreleased objects. So in your parse method you need to create (and release) NSAutoreleasePool object:
- (void)parse{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
...
// your method implementation
...
[pool release];
}

XMLParser delegate and memory leaks

I am building an application that has to handle the parsing of several different kinds of XML files. As I want to standardize the procedure as much as possible, I created a singleton class which handles the parsing of any XML data. The class is handed two options, a unique identifier telling it what kind of XML data it is going to parse and the data itself. Within the class, there is the following function which does the parsing and returns an NSMutableArray object containing the results:
- (NSMutableArray*) initAPIDataParse:(NSData *)data APIRequestType:(int)requestType {
// Init parser
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
// Set delegate for parser
if (requestType == kXMLParserTypeOne) {
[parser setDelegate:[[[XMLParserOne alloc] init] autorelease]];
} else if (requestType == kXMLParserTypeTwo) {
[parser setDelegate:[[[XMLParserTwo alloc] init] autorelease]];
} // etc.
// let's parse the XML
[parser parse];
[parser release];
return lastParsedDict; //lastParsedDict is the NSMutableArray object returned from the Parser delegate
}
Above code works like a charm, except that if you parse the same type of XML multiple times this line leaks (which makes sense):
[parser setDelegate:[[[XMLParserOne alloc] init] autorelease]];
I have tried several things to resolve this issue like creating an instance variable with an instance of the delegate and releasing it whenever the same type of XML Parser was asked for again, yet it didn't work.
I am glad for any help here, thanks a lot!
Delegates objects are never retained. So using an auto-released object for them is mostl likely going to end up in a crash.
I refactored your code:
- (NSMutableArray*) parseData: (NSData*) data withAPIRequestType: (int) requestType
{
NSMutableArray* result = nil;
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
if (parser != nil)
{
switch (requestType) {
case kXMLParserTypeOne:
delegate = [XMLParserOne new];
break;
case kXMLParserTypeTwo:
delegate = [XMLParserTwo new];
break;
}
if (delegate != nil)
{
[parser setDelegate: delegate];
[parser parse];
result = [delegate.result retain];
[delegate release];
}
[parser release];
}
return [result autorelease];
}