I am new to Objective C, so I'm not really even sure what this message means:
EXC_BAD_ACCESS
When executing the following code:
-(void)HelloWorld
{
NSURL *url = [NSURL URLWithString:#"http://example.com/service.asmx/HelloWorld"];
NSMutableURLRequest *request =[NSMutableURLRequest requestWithURL: url];
//do post request for parameter passing
[request setHTTPMethod:#"POST"];
//set the content type to JSON
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection release];
[request release];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// Store incoming data into a string
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}
I'm attempting to integrate with the Json Framework.
I call HelloWorld, which executes an async request to my service. What's strange, is that it worked one time, and now I get this EXC_BAD_ACCESS message every subsequent time. Any ideas what would be causing this?
You shouldn't be releasing the request. It's already autoreleased.
EXC_BAD_ACCESS means you have a bad pointer. In your case, it's because you are releasing the request when it's already autoreleased.
There's also another problem with your code (unrelated to the crash). You create an NSURLConnection and immediately release the connection after creation. When creating an asynchronous connection, you should release the connection in the delegate methods (if connection fails or if connection did finish loading).
Related
How can I detect if an NSURLConnection failure is due to server being inaccessible?
I checked the server's logs and there is no mention of the app's calls in these cases when the NSURLConnection failed. However, could it be that trying to initiate the NSURLConnection (see below) failed for a different reason?
I implement the call to NSURLConnection via a wrapper with the following init function:
-(id)initWithURL:(NSURL*)url
postData:(NSData*)postData
responseData:(NSMutableData*)responseData
delegate:(id)delegate
doneSelector:(SEL)doneSelector
errorSelector:(SEL)errorSelector {
if(self=[super init]) {
_url = [url retain];
_postData = [postData retain];
_responseData = [responseData retain];
_delegate = [delegate retain];
_doneSelector = doneSelector;
_errorSelector = errorSelector;
// Set up request
NSMutableURLRequest* request = [[[NSMutableURLRequest alloc] init] autorelease];
[request setURL:_url];
[request setHTTPMethod:#"POST"];
[request setValue:[NSString stringWithFormat:#"%d",[_postData length]] forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:_postData];
// Kick off the connection
NSURLConnection* connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
if(!connection) {
[_delegate performSelector:_errorSelector];
}
}
return self;
}
We never encountered this problem during our testing (and 99% of the time the URL connection works flawlessly for our users) so I am unable to say where exactly the NSURLConnection fails. I do know though that when it fails the errorSelector is called with an empty _responseData string.
Do you see anything in the above code that may fail on rare occasions?
Any idea how to find the cause of the connection failures?
Thanks in advance!
The URL is written properly, I tested it in the browser with data and it sends properly, but when I make the request, it returns that it is successful, but it does not actually write the data. Any idea?
- (void)writeAboutMe:(NSString *)about withIcebreaker:(NSString *)icebreaker
{
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
NSString *urlString = [NSString stringWithFormat:#"http://nailorbail.net63.net/submit_about_and_icebreaker.php?username=%#&about=%#&icebreaker=%#",[SignInViewController getUsernameString] ,about,icebreaker];
NSLog(#"%#",urlString);
[request setURL:[NSURL URLWithString:urlString]];
[request setHTTPMethod:#"GET"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Current-Type"];
NSURLConnection *conn = [[NSURLConnection alloc]initWithRequest:request delegate:self];
if(conn)
NSLog(#"Connection Successful");
else
NSLog(#"Connection could not be made");
[conn release];
}
It could be an encoding issue. What kinds of characters are in getUsernameString, about, and icebreaker? As Maudicus mentioned, you need to handle special characters in the URL yourself.
Try:
urlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]
You have set up an asynchronous connection. Do you implement the NSURLConnection delegate protocol methods? Are any of them being called?
The creation of the connection instance doesn't say anything about it's success.
Check out some tutorials, like this one.
I have a little Mac application which should be able to post Data to my web server which saves the data in a database. Now that's the Code I have now:
NSData *postData = [urlString dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%d", [postData length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:#"http://..."]];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
NSURLConnection * connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
if (connection) NSLog(#"Done");
And it works fine. But now I want to check whether the data was correct (and stored in the database) or something (like eMail) is wrong. The PHP file prints e.g. "email incorrect" out if the E-Mail is not correct.
But how can I fetch this data (which PHP prints out) in Xcode that the App knows whether it was successful or not?
Thanks for answers!
You need to implement the NSURLConnectionDelegate methods connection:didReceiveData: and connectionDidFinishLoading:
According to the docs didReceiveData: may be called multiple times per NSURLRequest (i.e. the response will not always arrive all at once) so the recommended method is to append the incoming data to buffer during connection:didReceiveData: and then do any processing on the data in connectionDidFinishLoading:.
You could create a property on your class like this:
#property (nonatomic, strong) NSMutableData *dataBuffer;
And instantiate your buffer during viewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
self.dataBuffer = [[NSMutableData alloc] init];
// do any other setup your class requires...
}
And then implement the delegate methods:
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
// clear the buffer in case it has been used previously
[self.dataBuffer setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[self.dataBuffer appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection*)connection
{
NSString *response = [NSString stringWithUTF8String:[self.dataBuffer bytes]]);
NSLog(#"response from HTTP request=>%#", response);
}
This can all also be done using a third-party networking library like ASIHTTPRequest (which is no longer under active develoment) or AFNetworking, but sometimes those can be overkill depending upon what you are trying to accomplish
Implement the delegate method for the NSURLConnection,
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response.
This method is called by the app when the request finishes. You can access response data using the 'response' parameter.
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;
Then just convert the 'data' parameter into a string using:
NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
Then you can search the response for whatever string you want, e.g., "email incorrect".
PS: I generally don't use NSURLConnection/NSURLRequest for HTTP requests, I'd recommend you check out ASIHTTPRequest for really simple HTTP requests/connections.
Hope this helps.
The goal is to do a simple username/password authentication by querying a database. Until the connection is working decently my php destination file simply has following code:
echo "Posted: " . $_POST['email'];
The code to do this synchronously is this:
NSString *post = [[NSString alloc] initWithFormat:#"email=%#&password=%#", self.email.text, ..]; // .. simplified keychainItem
NSData *postEncoded = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:NO];
NSString *postLength = [NSString stringWithFormat:#"%d", [postEncoded length]];
NSURL *url = [NSURL URLWithString:#"http://eng.studev.groept.be/web2.0/a11_web02/improver/app/testPost"];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:url];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postEncoded];
NSError *error = nil;
NSURLResponse *response = nil;
NSData *encodedData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString *data=[[NSString alloc]initWithData:encodedData encoding:NSUTF8StringEncoding];
NSLog(#"Data? %#",data);
The correct value is shown as an echo. But when trying to do this asynchronously, I get following php error: "Undefined index: email".
I try to start the asynchronous request with this line:
[[NSURLConnection connectionWithRequest:request delegate:self] start];
Then, I have the delegate method connection:didReceiveResponse, but there I cannot seem to get the data out... Or do I need another delegate method? Also, how 'safe' is it to check the result of your query by using just an echo (do I need/want a stream maybe?) ??
Tia
EDIT
Problem related to the server, not to objective-C code. Asked a new question to reach the correct audience: $_POST remaining empty
#ott is on the right track, I'll try to clarify.
You don't need start as he says. It's benign as the connection will start automatically.
initWithRequest:delegate and connectionWithRequest:delegate: are equivalent except for the retain state of the new connection object.
The real problem is b/c you are using connectionWithRequest:delegate the returned connection is autoreleased at the end of the run loop and you are not retaining it in a property. Therefore, the connection never starts.
The solution is to add a property #property (nonatomic, retain) NSURLConnection *connection to your class and set this property to the connection returned from connection:withRequest:
You then release the connection in the completion methods connection:didFinishLoading and connection:didFailWithError:.
The start is wrong here. Simply use
self.connection = [NSURLConnection connectionWithRequest:request delegate:self];
with NSURLConnection *connection; defined. See the class reference for connectionWithRequest. start is to be used with initWithRequest:delegate:.
I'm a novice in iOS developing, and have some problems with understanding web service organization. I want to send a Get query to the URL. And I do it so:
-(BOOL) sendLoginRequest{
NSString *getAction = [NSString stringWithFormat:#"action=%#&username=%password=%#",#"login",self.log.text, self.pass.text];
NSString *getUserName = [NSString stringWithFormat:#"username=%#",self.log.text];
NSString *getPassword = [NSString stringWithFormat:#"username=%#",self.pass.text];
NSData *getDataAction = [getAction dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *getLengthAction = [NSString stringWithFormat:#"%d", [getDataAction length]];
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
[request setURL:[NSURL URLWithString:#"http:http://www.site.fi/api/"]];
[request setHTTPMethod:#"GET"];
[request setValue:getLengthAction forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:getLengthAction];
self.urlConnection = [[[NSURLConnection alloc] initWithRequest:request delegate:self] autorelease];
NSAssert(self.urlConnection != nil, #"Failure to create URL connection.");
// show in the status bar that network activity is starting
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
}
the answer may be "true" or "false"
but how can I take this answer?
You should define next methods to get answer:
Start connection: [self.urlConnection start];
Check server response:
- (void)connection:(NSURLConnection *)theConnection didReceiveResponse:(NSURLResponse *)response
Collect data that servers sends you:
- (void)connection:(NSURLConnection *)theConnection didReceiveData:(NSData *)data
Be sure to manage errors:
- (void)connection:(NSURLConnection *)theConnection didFailWithError:(NSError *)error
Check received data:
- (void)connectionDidFinishLoading:(NSURLConnection *)theConnection
To be more sure that you correctly understood me check NSURLConnection Class Reference
Send [self.urlConnection start]; and implement the NSURLConnectionDelegate methods to receive the response. Alternatively use ASIHTTPRequest and the block handlers, which to my way of thinking are much easier to write for beginners, provided you don't need to run on iOS pre-4.1.
You will gather the data returned as NSData; just convert that to a string, and either call boolValue on the string (check the docs for its rather strange tests), or use a specific set of your own tests.