I'm trying to parse some text from a JSON-file on my server. There's three different values I'm parsing from the file: "value1":"some_value", "value2":"some_value", "value3":"some_value".
I'm declaring a NSMutableArray called statsHome which I initializing in the viewDidLoad method, like this: statsHome = [[NSMutableArray alloc] init];
The problem is that after I have initialized the array, I need to set up a NSDictionary. And if i would do this in the table view, I would write:
NSDictionary *stats = [self.statshome objectAtIndex:indexPath.row];
But I'm not parsing these values to the table view. I want to parse them to UILabels. So what I tried was to declare new NSUInteger. Because I can't use indexPath.row in the viewDidLoad method. I called it statsIndex.
But when I launch the app it crashes and gives me this error message: Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array'
The rest of the code looks like this:
#interface DEMOHomeViewController () {
NSUInteger statsIndex;
}
#end
#implementation DEMOHomeViewController
#synthesize statsHome;
#synthesize twitterFollowers;
#synthesize facebookLikes;
#synthesize instagramFollowers;
- (void)viewDidLoad
{
[super viewDidLoad];
statsHome = [[NSMutableArray alloc] init];
NSDictionary *stats = [self.statsHome objectAtIndex:statsIndex];
value1.text = [stats objectForKey:#"value1"];
value2.text = [stats objectForKey:#"value2"];
value3.text = [stats objectForKey:#"value3"];
NSURL *url1 = [[NSURL alloc] initWithString:#"the-json-file-with-the-values.php/file.json"];
NSURLRequest *request1 = [[NSURLRequest alloc] initWithURL:url1];
AFJSONRequestOperation *operation1 = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
self.statsHome = [[NSArray alloc] initWithArray:JSON];
[self.activityIndicatorView stopAnimating];
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"Request Failed with Error: %#, %#", error, error.userInfo);
}];
[operation1 start];
}
#end
Error is correct: you are trying to get data from an array before data is set. You should do something like in code below.
- (void)viewDidLoad
{
[super viewDidLoad];
NSURL *url1 = [[NSURL alloc] initWithString:#"the-json-file-with-the-values.php/file.json"];
NSURLRequest *request1 = [[NSURLRequest alloc] initWithURL:url1];
AFJSONRequestOperation *operation1 = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
[self.activityIndicatorView stopAnimating];
[self updateDataWithJSON:JSON]; // <- Here we will update our data
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"Request Failed with Error: %#, %#", error, error.userInfo);
}];
[operation1 start];
}
- (void)updateDataWithJSON:(id)JSON
{
self.statsHome = [[NSArray alloc] initWithArray:JSON];
NSDictionary *stats = [self.statsHome objectAtIndex:statsIndex];
value1.text = [stats objectForKey:#"value1"];
value2.text = [stats objectForKey:#"value2"];
value3.text = [stats objectForKey:#"value3"];
}
Let me give you an advice. Seems like your statsIndex initialised in other part of your app. In this case it's better to check if statsIndex is suitable for array length every time you access this array. Otherwise it could be a reason of app crash in some cases: For example you got your array in other controller and it has 10 elements. You select last element but reload a request in your viewDidLoad of DEMOHomeViewController. And in this time array has only 9 elements (last element was deleted already by someone else). -> Crash
NSURL *url = [NSURL URLWithString: [NSString stringWithFormat:#"url"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"GET"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
NSString *authStr = [NSString stringWithFormat:#"%#:%#", #"usernmae", #"password"];
NSData *authData = [authStr dataUsingEncoding:NSUTF8StringEncoding];
NSString *authValue = [NSString stringWithFormat:#"Basic %#", [authData base64EncodedStringWithOptions:0]];
NSLog(#"%#",authValue);//
[request setValue:authValue forHTTPHeaderField:#"Authorization"];
[request setURL:url];
NSLog(#"%#",url);
NSError *error;
NSHTTPURLResponse *response;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSLog(#"Response code: %ld", (long)[response statusCode]);
NSLog(#"Data is %#",data);
Related
I'm trying to change allow a cancellation, future order, and food preparation time through an Asynchronous way by using the POST Method.
I'm new to IOS Development, please give clear code and suggestions, heartful thank you whose are helps.
Here I'm code:
Settings.m
-(void) saveButtonPressed
{
lblsaveSucessful.textAlignment=NSTextAlignmentCenter;
lblsaveSucessful.text=#"Sucessfully saved";
[lblsaveSucessful sizeToFit];
[vwSettings addSubview:lblsaveSucessful];
NSLog(#"button exe");
NSURL *url = [NSURL URLWithString:#"https://www.ecloudbiz.com/Services/RestaurantAppService.svc/json/UpdateGeneralSettings?APIKEY=cbe55b66-0987-4cd4-81e9-73ae18888b9c"];
urlRequest = [NSURLRequest requestWithURL:url];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSMutableURLRequest *request=[[NSMutableURLRequest alloc] init];
[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (!error) {
//NSLog(#"Error,%#", [error localizedDescription]);
NSString *string = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSLog(#"%#", string);
NSError *jsonError = nil;
NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&jsonError];
NSMutableData *postBody=[NSMutableData data];
//Convert the String to Data
[postBody appendData:[[NSString stringWithFormat:#"{\"GeneralSettings\":{\"AllowCancellation\":\"%d\",\"AllowFutureOrder\":\"%d\",\"AppId\":\"7258400b-fec8-4399-9c6c-dce6752ffbf7\",\"AutoCompleteOrders\":\"true\",\"FoodPreparationTime\":\"%#\",\"FoodPreparationTimeType\":\"Minutes\",\"CreatedUser\":\"98eca785-4f90-48f4-8543-23e835f76101\",\"CancellationTime\":\"10 Minutes\",\"LocationId\":\"8652f07c-b2d1-4d2b-aa0f-591e60dca21c\",\"MoreItems\":\"0\",\"OrdersMadeUpto\":\"90 Days\",\"ItemProcessingMinutes\":\"10\",\"ReceiveCancelOrderEmail\":\"true\",\"ReceiveCancelOrderNotification\":\"true\",\"ReceiveCancelOrderText\":\"true\",\"Taxlabel\":\"Sales Tax\",\"Tax\":\"5.8\",\"TakeOutorders\":\"true\",\"DeliveryOrders\":\"true\",\"CateringOrders\":\"true\",\"GuestCheckout\":\"true\"}}",Alwcncl,Alwfuture,txtFp.text]dataUsingEncoding:NSUTF8StringEncoding]];
//Apply the data to the body
[request setHTTPBody:postBody];
NSString *TotalSvc=[NSString stringWithFormat:#"%#",[[NSString alloc] initWithData:postBody encoding:NSUTF8StringEncoding]];
NSLog(#"%#", TotalSvc);
}
else {
//NSLog(#"%#", [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]);
}
}];
The screen looks below:
enter image description here
settings page
I am creating an asynchronous NSURLconnection in a popup view in ios.
To implement the asynchronous NSURLconnection I implement the methods of the NSURLDelegate.
The problem occurs when the user taps outside the popup view and the view is dismissed.
leaving the nsurlconnection callbacks and other actions inside the view incomplete.
How can I assure that the actions inside the popup complete inspite of the dismissal of the view?
I tried putting an activity indicator inside the popup view till the actions are completed, but even then a tap outside the popup view dismisses the view.
I dont want the user to be left with an inactive app till actions are completed, instead I want the actions to be completed in the background.
If you want to send an asynchronous connection you can use this methods.
GET REQUEST
-(void)placeGetRequest:(NSString *)action withHandler:(void (^)(NSURLResponse *response, NSData *data, NSError *error))ourBlock {
NSString *url = [NSString stringWithFormat:#"%#/%#", URL_API, action];
NSURL *urlUsers = [NSURL URLWithString:url];
NSURLRequest *request = [NSURLRequest requestWithURL:urlUsers];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:ourBlock];
}
POST REQUEST
-(void)placePostRequest:(NSString *)action withData:(NSDictionary *)dataToSend withHandler:(void (^)(NSURLResponse *response, NSData *data, NSError *error))ourBlock {
NSString *urlString = [NSString stringWithFormat:#"%#/%#", URL_API, action];
NSLog(urlString);
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
// Creamos el JSON desde el data
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dataToSend options:0 error:&error];
NSString *jsonString;
if (! jsonData) {
NSLog(#"Got an error: %#", error);
} else {
jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSData *requestData = [NSData dataWithBytes:[jsonString UTF8String] length:[jsonString lengthOfBytesUsingEncoding:NSUTF8StringEncoding]];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setValue:[NSString stringWithFormat:#"%d", [requestData length]] forHTTPHeaderField:#"Content-Length"];
[request setHTTPBody: requestData];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:ourBlock];
}
}
EXAMPLE OF USE
- (void) getMyMethod:(NSString *)myParam1
myParam2:(NSString *)myParam2
myParam3:(NSString *)myParam3
calledBy:(id)calledBy
withSuccess:(SEL)successCallback
andFailure:(SEL)failureCallback{
[self placeGetRequest:[NSString stringWithFormat:#"api/myMethod?myParam1=%#&myParam2=%#&myParam3=%#",myParam1, myParam2, myParam3]
withHandler:^(NSURLResponse *response, NSData *rawData, NSError *error) {
NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
NSInteger code = [httpResponse statusCode];
NSLog(#"%ld", (long)code);
if (code == 0){
// error
} else if (!(code >= 200 && code < 300) && !(code == 500)) {
NSString *string = [[NSString alloc] initWithData:rawData
encoding:NSUTF8StringEncoding];
NSLog(#"ERROR (%ld): %#", (long)code, string);
[calledBy performSelector:failureCallback withObject:string];
} else {
// If you receive a JSON
NSMutableDictionary *result = [NSJSONSerialization JSONObjectWithData:rawData options:0 error:nil];
// If you receive an Array
// NSArray *result = [NSJSONSerialization JSONObjectWithData:rawData options:0 error:nil];
// If you receive a string
// NSString *result = [[NSString alloc] initWithData:rawData encoding:NSUTF8StringEncoding];
[calledBy performSelector:successCallback withObject:result];
}
}];
}
CALL YOU MUST DO IN YOUR VIEW/CONTROLLER/ETC
(...)
[api getMyMethod:myParam1Value myParam2:myParam2Value myParam3:myParam3Value calledBy:self withSuccess:#selector(getMyMethodDidEnd:) andFailure:#selector(getMyMethodFailureFailure:)];
(...)
// Don't forget to set your callbacks functions or callbacks will do your app crash
-(void)getMyMethodDidEnd:(id)result{
// your actions with the result
// ...
}
-(void)getMyMethodFailure:(id)result{
// your actions with the result
// ...
}
To prevent the dismissal of popup view when tapping out side u need to implement this delegate method
- (BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController
{
return NO;
}
dismiss it by using the action
- (void)someAction
{
//check the operations are completed
.....
.....
[popoverController dismissPopoverAnimated:YES];
}
I'm searching for a good tutorial for Restkit 2. Everywhere I'm seeing, they are talking about Object Mapping. Is it not possible to use Restkit and obtain a JSON as string and then use the JSON directly.
AFNetworking Does the Job,
AFNetworking can be installed using cocoapads as shown here,
A sample request using AFNetworking:
NSURL *url = [[NSURL alloc] initWithString:#"https://www.ez-point.com/search"];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
[request setValue:#"xxxxxxxxxxx" forHTTPHeaderField:#"Authorization" ];
[request setHTTPMethod:#"GET"];
NSMutableDictionary *jsonDic = [[NSMutableDictionary alloc]init];
[jsonDic setValue:#"UJO526" forKey:#"search_text" ];
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonDic options:NSJSONWritingPrettyPrinted error:nil];
[request setHTTPBody:jsonData];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
AFJSONRequestOperation *operation =
[AFJSONRequestOperation JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSArray *searchResults = JSON;
if ([searchResults count] == 1){
id result = [searchResults objectAtIndex:0];
double latitude = [[result valueForKey:#"latitude"] doubleValue];
double longitude = [[result valueForKey:#"longitude"] doubleValue];
NSString *ezPoint = [result valueForKey:#"value"];
NSString *tags = [result valueForKey:#"tags"];
[self setAnnotation:latitude ForLongitude:longitude withEZPoint:ezPoint WithTags:tags];
}
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
}
];
[operation start];
I am using AFNetworking to obtain JSON from a URL, the JSON is parsed and is supposed to be converted into an NSData format which is then in turn put into an array. However it doesn't seem to be working. I think i'm being stupid because it worked previously but now-
-(void)loadFromServer{
NSString *trendsURL = [NSString stringWithFormat:#"http://myurl.com/data.json"];
NSURL *url = [NSURL URLWithString:trendsURL];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFJSONRequestOperation *operation = [AFJSONRequestOperation
JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id json) {
self.results = [json valueForKeyPath:#"data"];
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
}];
[operation start];
NSError *anError = nil;
NSArray *parsedElements = [NSJSONSerialization JSONObjectWithData:elementsData
options:NSJSONReadingAllowFragments
error:&anError];
for (NSDictionary *aModuleDict in parsedElements){
MosData *aMosModule = [[MosData alloc] initWithDictionary:aModuleDict];
[elements addObject:aMosModule];
}
}
The data is displayed in a collection like view separately, there is no problem with this separate view as it works when I access data from a file rather than server.
-(void)loadFromDisk{
NSString *pathString = [[NSBundle mainBundle] pathForResource:#"data" ofType:#"json"];
NSData *elementsData = [NSData dataWithContentsOfFile:pathString];
NSError *anError = nil;
NSArray *parsedElements = [NSJSONSerialization JSONObjectWithData:elementsData
options:NSJSONReadingAllowFragments
error:&anError];
for (NSDictionary *aModuleDict in parsedElements){
MosData *aMosModule = [[MosData alloc] initWithDictionary:aModuleDict];
[elements addObject:aMosModule];
}
}
The JSON that is fetched is like so:
{
"imageLink": "http://link.com/image.jpg",
"size": 1,
"title": "Food"
}
I gave it another go, and still it's not working. results is a declared NSArray.
-(void)loadFromServer{
NSString *trendsURL = [NSString stringWithFormat:#"http://url.com/data.json"];
NSURL *url = [NSURL URLWithString:trendsURL];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFJSONRequestOperation *operation = [AFJSONRequestOperation
JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id json) {
NSLog(#"Custom Mosaic: %#", json);
self.results = [json valueForKeyPath:#"data"];
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
}];
[operation start];
for (NSDictionary *aModuleDict in self.results){
MosData *aMosModule = [[MosData alloc] initWithDictionary:aModuleDict];
[elements addObject:aMosModule];
}
}
I think the issue might actually be this having played around a little, for some reason, it won't pick up the results of the data parsed in the AFNetworking operation.
-(id)init{
self = [super init];
if (self){
elements = [[NSMutableArray alloc] init];
[self loadFromServer];
}
return self;
}
// WWDC 2012 proposed method
+ (CustomMosDatasource *)sharedInstance {
static CustomMosDatasource *sharedInstance;
if (sharedInstance == nil)
sharedInstance = [CustomMosDatasource new];
return sharedInstance;
}
#pragma mark - MosViewDatasourceProtocol
-(NSArray *)mosElements{
NSArray *retVal = elements;
return retVal;
}
The results of the log is just JSON:
Custom Mosaic: {
data = (
{
imageFilename = "http://distilleryimage6.instagram.com/9969123a6af311e2b6c722000a9d0edd_7.jpg";
size = 1;
title = "Title";
},
AFJSONRequestOperation *operation = [AFJSONRequestOperation
JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id json) {
self.results = [json valueForKeyPath:#"data"];
NSError *anError = nil;
NSArray *parsedElements = [NSJSONSerialization JSONObjectWithData:elementsData
options:NSJSONReadingAllowFragments
error:&anError];
for (NSDictionary *aModuleDict in parsedElements){
MosData *aMosModule = [[MosData alloc] initWithDictionary:aModuleDict];
[elements addObject:aMosModule];
}
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
}];
[operation start];
Your json don't seem to have keyPath "data", remove the valueForKeyPath:#"data", please paste the result of "NSLog(#"Custom Mosaic: %#", json)" in your question.
The operation is asynchronized. The success block is called after the request returns data. Please put code in the success block like this
-(void)loadFromServer{
NSString *trendsURL = [NSString stringWithFormat:#"http://url.com/data.json"];
NSURL *url = [NSURL URLWithString:trendsURL];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFJSONRequestOperation *operation = [AFJSONRequestOperation
JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id json) {
NSLog(#"Custom Mosaic: %#", json);
// your json doesn't have keyPath "data"
self.results = json;
// Codes moved into success block
for (NSDictionary *aModuleDict in self.results){
MosData *aMosModule = [[MosData alloc] initWithDictionary:aModuleDict];
[elements addObject:aMosModule];
}
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
}];
[operation start];
}
I'm trying to get a JSon string but some words has "á, é, ç", etc.
The JSon is:
{"Error":"", "Result":{"Transacoes": [{"ClienteID":"1","ID":"915","Banco":"Bradesco","Fornecedor":"","Tipo":"Cartão de crédito - Bradesco Visa","ValorCredito":"0,0000","ValorDebito":"4000,0000","Vencimento":"","Pagamento":"03/08/2012 00:00:00","Descricao":"Cartão Bradesco Visa","Lançamento":"03/08/2012 15:18:12"},{"ClienteID":"1","ID":"916","Banco":"Bradesco","Fornecedor":"","Tipo":"Alinhamento da Conta Bancária","ValorCredito":"22398,9200","ValorDebito":"0,0000","Vencimento":"","Pagamento":"02/08/2012 00:00:00","Descricao":"FGTS","Lançamento":"07/08/2012 11:12:16"}]}}
And the code is:
-(void)viewWillAppear:(BOOL)animated {
NSString *urlAddress = [NSString stringWithFormat:#"http://SITE?action=transacoes&AuthToken=%#&DataDe=02/08/2012&DataAte=03/08/2012", self.usuario.authToken];
NSURL *url = [NSURL URLWithString:urlAddress];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest: request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSLog(#"%#", JSON);
}
failure: ^(NSURLRequest *request , NSURLResponse *response , NSError *error , id JSON){
NSLog(#"ERROR: %#", error);
}];
[operation start];
}
Your app throws Exception because it can't get data from server ,which you are requesting. SO first make sure it receives some data and then implement following code
Try Following code to parse your json data, i tried with my app, its working fine with that special symbols as well.
NSString *urlAddress = [NSString stringWithFormat:#"http://SITE?action=transacoes&AuthToken=%#&DataDe=02/08/2012&DataAte=03/08/2012", self.usuario.authToken];
NSURL *url = [NSURL URLWithString:urlAddress];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSHTTPURLResponse* urlResponse = nil;
NSError *error = nil;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&error];
if([responseData bytes] > 0)
{
// It will work only IOS 5.0 or later version otherwise you can use any third party JSON parsers (eg. SBJSON)
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:responseData
options:NSJSONReadingMutableLeaves
error:&error];
NSLog(#"%#",[[[[json objectForKey:#"Result"] objectForKey:#"Transacoes"] objectAtIndex:1] valueForKey:#"Descricao"]);
NSLog(#"%#",[[[[json objectForKey:#"Result"] objectForKey:#"Transacoes"] objectAtIndex:1] valueForKey:#"Tipo"]);
}