Also I know that anything that I create using alloc I have to release it, but when I try to release 'request' object using [request release]; it throws the following error:
Program received signal: “EXC_BAD_ACCESS”.
kill
error while killing target (killing anyway): warning: error on line 2179 of "/SourceCache/gdb/gdb-1510/src/gdb/macosx/macosx-nat-inferior.c" in function "macosx_kill_inferior_safe": (os/kern) failure (0x5x)
You are creating the request using requestWithURL:cachePolicy:timeoutInterval:. Since that method name doesn't begin with "alloc" or "new" or contain "copy", according to the Memory Management Rules you don't own it and so should not be releasing it (unless you call retain on it explicitly, of course).
As for efficiency, the code seems fine. Note though that if the user can trigger a second load before the first completes that you will have problems; the solution to that is to either prevent such a thing or to save the NSURLConnection object created in load into an ivar and then have the pseudo-delegate methods check that against the passed connection before doing anything else. It's also a good idea to set the ivar to nil when you release the object it formerly contained, as then you cannot accidentally use the released object. And I note the variable name for your "authentication failed" alert is alertsuccess, that's misleading ;)
Try this in your load function:
NSMutableURLRequest *request;
request=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:pageUrl]];
NSURLResponse *response;
NSError *error = [[NSError alloc] init];
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];`
NSString *responseString = [NSString stringWithCString:[data bytes] length:[data length]];
`
Related
I am getting data from an NSURL connection like below. The code works, but I get a compiler warning that says "Unused variable strResult."
I don't actually need to use what is returned. I just need the URL to be executed.
How can I go about modifying this to get rid of the warning?
NSString *strURL = [NSString stringWithFormat:#"http://www.site.com/file.php?id=%#", id];
NSData *dataURL = [NSData dataWithContentsOfURL:[NSURL URLWithString:strURL]];
NSString *strResult = [[NSString alloc] initWithData:dataURL
encoding:NSUTF8StringEncoding];
Thank you!
You have initialized and assigned data in strResult variable but you haven't used that variable.
So use that variable or just NSLog#("%#",strResult)
i suggest if the variable is not useful then remove that variable it occupies memory
You are not using the strResult anywhere after declaring ie the Warning .
Just log it you can see the warning goes off.
NSString *strResult = [[NSString alloc] initWithData:dataURL
encoding:NSUTF8StringEncoding];
NSLog(#"%#", strResult);
use NSURLConnection and call it's static method:
[NSURLConnction sendSynchronousRequest:.....]
and if you wanna send Asynchronous request use:
[NSURLConnection sendAsynchronusRequest:....]
The compiler just informs you that you created a variable and you are not using it (yet) .. so the best solution is to use it, as a return value of your method. It would help to see the complete implementation of the relevant method to help you better.
Hope this clarifies the warning.
You get that warning, because nowhere in your code, you actually use strResult.
Use it, and the warning is gone :) Or, remove the statement if you don't actually need the repsonse.
I'm getting this error
malloc: * * * error for object 0x8a591d4: incorrect checksum for freed object - object was probably modified after being freed.
*** set a breakpoint in malloc_error_break to debug
No memory available to program now: unsafe to call malloc
No memory available to program now: unsafe to call malloc
It comes from this line
NSString *plistPath = [[NSBundle mainBundle] pathForResource:#"Info"
ofType:#"plist"];
NSData *plistData = [NSData dataWithContentsOfFile:plistPath];
NSDictionary *loadedPlist =
[NSPropertyListSerialization propertyListFromData:plistData
mutabilityOption:0 format:NULL errorDescription:NULL]; <<< this line
The value of plistData is set to Summary Unavailable
I'm not sure where to start ?
EDIT - added more code
I'm going to add another answer: it's also possible that you have ALREADY hosed the heap, and you're failing on propertyListFromData: just because it does a lot of allocations and happens to hit the bad spot. So edit your scheme in Xcode, and make sure you have all of the Memory Management items checked (in the Diagnostics tab of the Run task).
Have you set a breakpoint in malloc_error_break? This at least gives you a backtrace and you might see something of note. If nothing else, you could try po plistData from the GDB console.
BTW, while it may not help, I'd think dictionaryWithContentsOfFile: would be simpler.
How is Info.plist being stored? Is it a standard plist/xml file? Would the following solve the problem you are trying to solve, and possibly prevent this issue from happening?
NSString *plistPath = [[NSBundle mainBundle] pathForResource:#"Info"
ofType:#"plist"];
NSDictionary *loadedPlist = [[NSDictionary alloc] initWithContentsOfFile:plistPath];
Or if you want an auto-released object...
NSDictionary *loadedPlist = [NSDictionary dictionaryWithContentsOfFile:plistPath];
I want to handle freezing my program, when it load an xml from bad address.
I tryed it with using #try and #catch, but it doesn't work.
Can I use some alternative handling?
#try{
NSString *test=[[NSString alloc] initWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://%#:%#",addressLabel.text,portLabel.text]] encoding:NSUTF8StringEncoding error: nil];
}
#catch (NSException *ex) {
NSLog(#"Bad IP address");
return;
}
Run your XML Parser in NSThread and use notification for errors.
initWithContentsOfURL is a synchronous call. The control will return back from the function only on complete. Try this function is a worker thread so that your main thread will not be blocked.
If you use use NSThread then you have to dive into the memory management unless you are working in XCode 4.2 and using ARC.
So there are two ways for fetching the XML from the server.
1) Use NSURLConnection to get the xml as a NSData object and when you finish loading the data you can simply use that data to initialize an NSString Object. NSURLConnection sends asynchronous call to the server so it will not freeze your view.
2) You can use NSIncovationOperation and NSQueue to fetch your XML and it will also not effect your main thread. like
-(void)myMethod{
NSString *test=[[NSString alloc] initWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://%#:%#",addressLabel.text,portLabel.text]] encoding:NSUTF8StringEncoding error: nil];
[self performSelectorOnMainThread:#selector(handleString:) withObject:test];
}
You can use NSInvocationOperation object as follow
NSInvocationOperation *opr = [[NSInvocationOperation alloc] initWithTarget:self selector:#selector(myMethod) object:nil];
NSOperationQueue *queue= [NSOperationQueue new];
[queue addOperation:opr];
When the perform selector will be call then you can pass that XML string object to the handleString: method. like
-(void)handleString:(NSString*)xmlString{
// Do something with string
}
I hope that it clarifies a little bit of your confusion. All this was to give you an idea how can you achieve your goal without freezing your interface i.e main thread.
regards,
Arslan
You need to launch all long time operations on a second thread to avoid blocking the main thread. Use [self performSelector:#selector(yourXmlDownloadMethod)].
I have an external XML file which I want to be represented in an NSData object
I am doing this;
NSError *error;
NSString* contents = [NSString stringWithContentsOfUrl:[NSURL URLWithString:#"http://www.apple.com/"]
encoding:NSUTF8StringEncoding
error:&error];
NSData* xmlData = [contents dataUsingEncoding:NSUTF8StringEncoding];
But for some reasons, I am getting an error (does not respond)
Please help me.
Don't have time to test this out but I think you may want to try looking into NSData's dataWithContentsOfURL: or dataWithContentsOfURL:options:error: and get it directly as data.
Also, unless you just threw http://www.apple.com/ in as a placeholder, I don't believe the source of that page is valid XML. The following feed is valid xml: https://stackoverflow.com/feeds You could try that. with what you have now first and see if it works.
Hope this helps.
Updated:
Without my knowing your project, you may get some benefit from using TouchXML - https://github.com/mrevilme/TouchXML which handles XML very well including what you are trying to do:
CXMLDocument *xmlDoc = [[CXMLDocument alloc] initWithContentsOfURL:(NSURL *)inURL encoding:(NSStringEncoding)encoding options:(NSUInteger)inOptions error:(NSError **)outError];
In my app i need to download several plist.
to download a plist i use the NSURLconnection
in my code i use an UIAlertView with a UIActivityIndicator then when the download is finished i add a button to the alert to dismiss it.
To download the plist i use somewhere in my code an NSURL set to the adresse where the plist is, next i set a NSURLRequest with the url cache policy and a timeout interval.
Then i set my NSMutableData to the NSURL connection with a NSURLRequest.
In the delegate didReceiveData: i append data to my mutable data object, in the didFailWithError: i handle error. And finaly in the connectionDidFinishLoading i serialize my data to a plist so i can write to file my plist, and release my alertview.
My problem is : how can i do if i have sevetal file to download because the connectionDidFinishLoading is called each time my NSURLConnection is finished but i want to release my UiAlert when everything is finished. But when the first plist is downloaded my code in the connectionDidFinishLoading will fire.
here is my code :
in the view did load :
// set the UiAlert in the view did load
NSURL *theUrl = [NSURL URLWithString:#"http://adress.com/plist/myPlist.plist"];
NSURLRequest *theRequest = [NSURLRequest requestWithURL:theUrl cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
self.plistConnection = [[ NSURLConnection alloc] initwithRequest:theRequest delegate:self startImmediatly:YES];
//plistConnection is a NSURLConnection
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[incomingPListData appendData:data];
}
-(void)connection:(NSURLConnection *)connectionDidFailWithError:(NSError *)error {
// handle error here
}
-(void)connectionDidFinisloading:(NSURLConnection *) connection {
NSPropertyListFormat format;
NSString *serialErrorString;
NSData *plist = [NSPropertyListSerialisation propertyListFromData:incomingPlistData mutabilityOption:NSPropertyListImmutable format:&format errorDescription:&serialErrorString];
if (serialErrorString) {//error}
else { // create path and write plist to path}
// change message and title of the alert
so if i want todownload an another file where do i put the request the connection and how can i tell the didFinishLoading to fire code when all my file are downloaded.
thanks to all
You can iterate over an array of resources you wish to download, and allocate a request for each of them. It is possible to set a tag to a connection (e.g. the index of the URL in the array) which you can evaluate in the connectionDidFinishLoading. If you hold the information, which requests are sent and which are finished, you can easily see, if all files have been loaded.
I think unset provided a good answer. I understand that you don't get it (you will someday), as I remember myself being new to programming and such.
I therefore provide another, much simpler option to evaluate if all downloads did finish.
you simply use a counter that you define in your .h file,
int activeDownloads;
in your implementation (.m) File, wherever you start all your downloads, set activeDownloads to zero before any of your downloads start
activeDownloads = 0;
before you start a download you increase the number of activeDownloads
++activeDownloads;
if a download finishes or fails you decrease the same countervariable
- (void)connectionDidFinishLoading:(NSURLConnection *)connection { --activeDownloads;}
(i didn't write down the method that gets called if a download fails...
also everytime a connection finishes or fails you have to check if the one that finished or railed was the last one.
you do that by simply checking if activeDownloads is equal to zero. If that is the case, you can add the "close" Button to your AlertView.
The drawback of this solution is, that you're unable to track which connection succeeded and which failed. (well, you are, but activeDownloads don't help you with that)
hope i could help
cheers