NSJSONSerialization returns EXC_BAD_ACCESS - objective-c

I am parsing a JSON file created by a PHP-Script using NSJSONSerialization.
When I clear the code (Product - clear) it works perfectly. But when I stop the program and build it again without Product - clear, it will crash at this line with EXC_BAD_ACCESS.
I use ARC.
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:adresse]];
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSError *jsonParsingError = nil;
if (response == nil) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Connection" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show];
}
else {
if (![NSJSONSerialization JSONObjectWithData:response options:0 error:&jsonParsingError]) {
UIAlertView *jsonAlert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"JSON Parsingerror" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles: nil];
[jsonAlert show];
}
else {
jsonData = [NSJSONSerialization JSONObjectWithData:response options:0 error:&jsonParsingError];
Working around the problem caused by escaped unicode characters by adding this
NSString *escaped = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
NSString *name = [NSString
stringWithCString:[escaped cStringUsingEncoding:NSUTF8StringEncoding]
encoding:NSNonLossyASCIIStringEncoding];
NSData *responseData = [name dataUsingEncoding:NSUTF8StringEncoding];
responseData = [responseData subdataWithRange:NSMakeRange(0, [responseData length]-1)];
and changing
jsonData = [NSJSONSerialization JSONObjectWithData:response options:0 error:&jsonParsingError];
to
jsonData = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:&jsonParsingError];
results in a SIGABRT crash.
What am I doing wrong? It WORKS for the first time AFTER product clear but then crashes with EXC_BAD_ACCESS despite using ARC.
My JSON looks like that
[{"line":"ABC","date":"2013-10-02","description":"H\u00e4hnchenbrust mit Calvadosso\u00dfe (1,2,4,8)","art":"type1"},{"line":"DEF","date":"2013-10-02","description":"Frika‌​dellen \u0084Polpette\u0093 (Rind) mit Sardellen und Tomaten (8)","art":"type1"},{"line":"ABC","date":"2013-10-03","description":"Salatteller mit Gem\u00fcseschnitzel (4,2,8)","art":"type2"},{"line":"ABC","date":"2013-10-27","description":"Nudel-H‌​ackfleisch-Pfanne (Rind) mit Schafsk\u00e4se (2,4)","art":"type1"}]

If you want to replace those escape sequences, you can use CFStringTransform:
NSMutableString *escaped = [[NSMutableString alloc] initWithData:response encoding:NSUTF8StringEncoding];
CFStringTransform((__bridge CFMutableStringRef)escaped, NULL, CFSTR("Any-Hex/Java"), YES);
NSData *unescapedData = [escaped dataUsingEncoding:NSUTF8StringEncoding];

I guess I solved the problem. I used a separate class JSONParser.h /.m which was build again and again. I now just parse using the code directly from the parental class and it is working.

Related

How to upload UIImage from iOS to Azure storage

I try to upload an image to Azure storage through MVC 4 web API. But the server side always return:
"Invalid length for a Base-64 char array or string."
Below is Objective-C code:
- (IBAction)btnUploadReceipt:(id)sender {
UIImage *img = self.imgReceipt.image;
NSData *dataObj = UIImagePNGRepresentation(img);
NSString *fff = [dataObj base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
//NSString *ddd = [self base64EncodeString:imgData];
//NSString *ddd = [dataObj base64EncodedString];
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"%#/api/upload/UploadAzure",baseUrl]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"Post"];
NSString *jsonData = [NSString stringWithFormat:#"FileName=%#&FileData=%#&FolderName=%#&UserName=%#&Point=%#&DateTime=%#&MerchantName=%#&OutletID=%#",fileName,fff,imgFolder,userName,#"3",dateTime,_mName,_mOutletID];
[request setHTTPBody:[jsonData dataUsingEncoding:NSUTF8StringEncoding]];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response,
NSData *data, NSError *connectionError)
{
if (data.length > 0 && connectionError == nil)
{
NSString * json =[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"%#",json);
if ([json isEqualToString:#"\"True\""]) {
NSLog(#"%#",#"Success Add Photo");
//[self dismissViewControllerAnimated:YES completion:nil];
//[[self navigationController]popViewControllerAnimated:YES];
}
else
{
UIAlertView *messageAlert = [[UIAlertView alloc]initWithTitle:#"Connection Error" message:#"Please Check Internet Setting" delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[messageAlert show];
}
}
else
{
UIAlertView *messageAlert = [[UIAlertView alloc]initWithTitle:#"Connection Error" message:#"Please Check Internet Setting" delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[messageAlert show];
}
}];
}
- (NSString *)base64String2 {
UIImage *img = self.imgReceipt.image;
NSData * data = [UIImagePNGRepresentation(img) base64EncodedDataWithOptions:NSDataBase64Encoding64CharacterLineLength];
return [NSString stringWithUTF8String:[data bytes]];
}
Anyone face this kind of problem?
Have you tried using the Azure Storage iOS Library? The Getting Started documentation should be able to help with your scenario.

Handling a String From a Web API Service in Object-C

I have a simple Web API Service POST
// POST api/values
public string Post(SimpleRequest request)
{
if (request == null || string.IsNullOrEmpty(request.Field1) || string.IsNullOrEmpty(request.Password))
return "Something is missing.";
return string.Format("Success. You sent {0}!", request.Field1);
}
Which is consumed in an a object-c method (for an iphone project):
- (IBAction)doSomethingButtonWasPressed:(id)sender {
NSString * urlString = #"http://192.168.0.XXX/api/Test";
NSDictionary *postDict = [[NSDictionary alloc] initWithObjectsAndKeys:
_field1.text, #"Field1",
_field2.text, #"Field2",
nil];
NSURL *url=[NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSData *req= [NSJSONSerialization dataWithJSONObject:postDict options:NSJSONWritingPrettyPrinted error:nil];
NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];//
[request setHTTPBody:req];
NSURLResponse* response;
NSError* error = nil;
NSData* responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSLog(#"The output is:%#",responseString);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle: #"Result"
message:responseString
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
It all works, except the result has "quotes" around it. I feel like maybe I'm missing a decoding step?
It's possible the service is returning JSON, like {"foo"} that would appear as a quoted string. Try interpreting the data as JSON with ...
NSError *error;
id result = [NSJSONSerialization JSONObjectWithData:responseData options:nil error:&error];
NSLog(#"result is %#, error is %#", result, error);

NSError and activating it while polling JSON data - Objective C

Trying to understand how/why NSError works in this case. I'm trying to do a simple UIAlertview when the JSON query returns no data (either the server is sending it or the user is not on internet). I have looked at about a dozen different answers and am just confusing myself more and more.
- (void)viewDidLoad
{
[super viewDidLoad];
dispatch_async(kBgQueue, ^{
NSData* data = [NSData dataWithContentsOfURL:
kLatestChartDataURL];
[self performSelectorOnMainThread:#selector(fetchedData:)
withObject:data waitUntilDone:YES];
});
}
- (void)fetchedData:(NSData *)responseData {
NSError *error = nil;
NSArray *theArray = [NSJSONSerialization
JSONObjectWithData:responseData
options:kNilOptions
error:&error];
NSDictionary *dict0 = [theArray objectAtIndex:147];
if (NO) {
UIAlertView *message = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"Data failed to load."
delegate:self
cancelButtonTitle:#"Ok"
otherButtonTitles:#"Retry",nil];
[message show];
}
I've also tried:
if (!theArray) {
and
BOOL results = [NSArray etc...
Any thoughts on this would be appreciated, I've also looked at the developer docs and Cocoa is Mygirlfriend examples, and my brain has turned to mush at this point.
Try this
NSError *error = nil;
NSArray *theArray = [NSJSONSerialization
JSONObjectWithData:responseData
options:kNilOptions
error:&error];
if (!theArray) { // DO THIS CHECK
NSLog(#"error: %#", error);
UIAlertView *message = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"Data failed to load."
delegate:self
cancelButtonTitle:#"Ok"
otherButtonTitles:#"Retry",nil];
[message show];
}
else
{
NSLog(#"parsed data");
    NSDictionary *dict0 = [theArray objectAtIndex:147];
}
If any error occurs while getting json from NSData then it will be recorded in object of NSError. So if this object is nil means there is no error while parsing json, and if that object holds value means there is some issue while parsing.

Parsing Json to handle and direct a user to view controller. Objective C

I have a Login screen and I POST username and password to a login page.
The webservice gives me 2 responses if the Login user details are correct I get a response of back from the request.
{"value":1}
and if the user details are wrong I get back from request.
{"value":0}
I have been able to parse that JSON Result to give me a log output of
value: 1 or value:0
I am battling to handle the parsed json e.g
//parse out the json data
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:urlData //1
options:kNilOptions
error:&error];
NSArray* defineJsonData = [json objectForKey:#"value"]; //2
NSLog(#"value: %#", defineJsonData); //3
if ([[json objectForKey:#"value"] isEqualToNumber:[NSNumber numberWithInt:1]])
{
HUD.customView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"37x-Checkmark.png"]];
HUD.mode = MBProgressHUDModeCustomView;
[HUD hide:YES afterDelay:0];
[self performSegueWithIdentifier: #"introScreenView" sender:self];
}
else {
HUD.customView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"37x-Checkmark.png"]];
HUD.mode = MBProgressHUDModeCustomView;
[HUD hide:YES afterDelay:0];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Wrong Credentials" message:#"Please try to login again" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
}
Here is the rest of my code.
- (void)myTask {
if ([userNameTextField.text isEqualToString:#""] || [passwordTextField.text isEqualToString:#""]) {
HUD.customView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"37x-Checkmark.png"]];
HUD.mode = MBProgressHUDModeCustomView;
[HUD hide:YES afterDelay:0];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Feilds Missing" message:#"Please Fill all the field" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
return;
}
NSString *data = [NSString stringWithFormat:#"UserName=%#&Password=%#",userNameTextField.text, passwordTextField.text];
NSData *postData = [data dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%d", [postData length]];
// preaparing URL request to send data.
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init] ;
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:request delegate:self];
NSString *url = [NSString stringWithFormat:#"http://www.ddproam.co.za/Central/Account/LogOnIOS?"];
[request setURL:[NSURL URLWithString:url]];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setHTTPBody:postData];
[request setTimeoutInterval:7.0];
NSURLResponse *response;
NSError *error;
NSData *urlData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString *str=[[NSString alloc]initWithData:urlData encoding:NSUTF8StringEncoding];
NSLog(#"Login response:%#",str);
NSHTTPCookie *cookie;
NSLog(#"name: '%#'\n", [cookie name]);
for (NSHTTPCookie *cookie in [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies])
{
NSLog(#"name: '%#'\n", [cookie name]);
NSLog(#"value: '%#'\n", [cookie value]);
NSLog(#"domain: '%#'\n", [cookie domain]);
NSLog(#"path: '%#'\n", [cookie path]);
}
//parse out the json data
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:urlData //1
options:kNilOptions
error:&error];
NSArray* defineJsonData = [json objectForKey:#"value"]; //2
NSLog(#"value: %#", defineJsonData); //3
if ([defineJsonData isEqual:0])
{
HUD.customView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"37x-Checkmark.png"]];
HUD.mode = MBProgressHUDModeCustomView;
[HUD hide:YES afterDelay:0];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Wrong Credentials" message:#"Please try to login again" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
}
else {
HUD.customView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"37x-Checkmark.png"]];
HUD.mode = MBProgressHUDModeCustomView;
[HUD hide:YES afterDelay:0];
[self performSegueWithIdentifier: #"introScreenView" sender:self];
}
if (theConnection) {
}
}
If response from the server is really just {"value":1}, then you correctly parse JSON to dictionary using NSJSONSerialization.
However under value key, there is an instance of NSNumber, not NSArray.
Your code to retrieve value and check it should look like this:
NSNumber *defineJsonData = [json objectForKey:#"value"];
NSLog(#"value: %#", defineJsonData);
if ([defineJsonData integerValue] == 0) {
NSLog(#"Wrong credentials");
}
else {
NSLog(#"Welcome :-)");
}

POST to web-server in Objective C

I've been working on a way to send a value to a web-server in objective c.
I think I have everything working on both ends, except for the fact that my value doesn't show up in the email that is sent out.
Here is my code, if someone could point out what I'm doing wrong, that would be great.
(dval is what's not showing up)
NSMutableString *mmessage = [[NSMutableString alloc]initWithString:#""];
[mmessage appendString:[NSString stringWithFormat:#"<p><b>Drink Name:</b> %#</p>", dval]];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"http://test.com/api/stuff/send"]];
NSMutableDictionary *postInfo = [NSDictionary dictionaryWithObject:[NSDictionary dictionaryWithObjectsAndKeys:mmessage, #"message", nil] forKey:#"form"];
NSError *e = nil;
NSData *postData = [NSJSONSerialization dataWithJSONObject:postInfo options:0 error:&e ];
__block int resp_code = 0;
[urlRequest setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[urlRequest setHTTPMethod:#"POST"];
[urlRequest setHTTPBody:postData];
[NSURLConnection sendAsynchronousRequest:urlRequest
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
resp_code = httpResponse.statusCode;
if(resp_code == 200){
NSDictionary *jsonObjects = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
if ([[jsonObjects objectForKey:#"status"] isEqualToString:#"success"]) {
UIAlertView *emailsuccess = [[UIAlertView alloc] initWithTitle:#"Email Successfully sent." message:nil delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[emailsuccess show];
}
else if ([[jsonObjects objectForKey:#"status"] isEqualToString:#"failed"]) {
UIAlertView *emailfailed = [[UIAlertView alloc] initWithTitle:#"Email Failed." message:[jsonObjects objectForKey:#"messages"] delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[emailfailed show];
}
else {
UIAlertView *emailfailed = [[UIAlertView alloc] initWithTitle:#"Email Response." message:[jsonObjects objectForKey:#"messages"] delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[emailfailed show];
}
}
}];