My app is crashing when updating my table view - ios

I am doing a database based application. My app needs to update a database table and simultaneously it needs to update the table view i.e. generated based on that particular database table.
Here's is the code i have written
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.courses.count;
}
-(void)viewWillAppear:(BOOL)animated {
self.usernameLBL.text = [NSString stringWithFormat:#"Welcome, %#", self.del.username];
[self loadCourses];
// NSLog(#"The courses count is %d", self.courses.count);
}
-(void)loadCourses {
NSString * stringUrl = [NSString stringWithFormat:"Some URL";
NSURL * uRL = [NSURL URLWithString:[stringUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSURLRequest * request = [NSURLRequest requestWithURL:uRL];
NSError * error;
NSData * results = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&error];
self.courses = [NSJSONSerialization JSONObjectWithData:results options:0 error:&error];
NSLog(#"The courses array count is %d", self.courses.count);
[self.tableView reloadData];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
NSDictionary * dict = self.courses[indexPath.row];
cell.textLabel.text = dict[#"name"];
cell.detailTextLabel.text = dict[#"id"];
return cell;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.courses = [[NSMutableArray alloc] init];
self.del = [[UIApplication sharedApplication] delegate];
NSString * strURL = [NSString stringWithFormat:"Some URL";
// NSLog(#"The username is %#", self.del.username);
NSURL * url = [NSURL URLWithString:[strURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSURLRequest * request = [NSURLRequest requestWithURL:url];
NSError * error;
NSData * data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&error];
// NSLog(#"The data is %#", data);
NSDictionary * result = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
// NSLog(#"The error is %#", error);
// NSLog(#"The value returned is %#", result[#"image"]);
if(![result[#"image"] isEqualToString:#"empty"]){
NSString * urlLocation = result[#"image"];
self.adminIMG.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[urlLocation stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]]]];
}
// Do any additional setup after loading the view.
}
- (IBAction)addNewCourse:(id)sender {
NSString * strURL = [NSString stringWithFormat:"Some URL";
NSURL * url = [NSURL URLWithString:[strURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSURLRequest * request = [NSURLRequest requestWithURL:url];
NSError * error;
NSData * results = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&error];
NSDictionary * dict = [NSJSONSerialization JSONObjectWithData:results options:0 error:&error];
if([dict[#"response"] isEqualToString:#"success"]) {
NSLog(#"New course added");
UIAlertView * success = [[UIAlertView alloc] initWithTitle:#"New course added successfully" message:#"You successfully added a new course" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles: nil];
[success show];
}else {
NSLog(#"Course not added");
}
[self.courses removeAllObjects];
[self viewDidLoad];
[self viewWillAppear:YES];
}
And i got this error.
Error: Evaluation[13335:60b] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFArray objectForKeyedSubscript:]: unrecognized selector sent to instance 0xb7d26d0'
I tried many solutions available on the internet but those are not working for me. Anyone can help me, please. Thanks in advance :)

your issue might be here
[self.courses removeAllObjects];
[self viewDidLoad];
[self viewWillAppear:YES];
you don't have to clear your array, try this:
function:
- (void)addCourse{
NSString * strURL = [NSString stringWithFormat:"Some URL";
NSURL * url = [NSURL URLWithString:
[strURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSURLRequest * request = [NSURLRequest requestWithURL:url];
NSError * error;
NSData * results = [NSURLConnection sendSynchronousRequest:request
returningResponse:nil error:&error];
NSDictionary * dict = [NSJSONSerialization JSONObjectWithData:results
options:0 error:&error];
if([dict[#"response"] isEqualToString:#"success"]) {
NSLog(#"New course added");
UIAlertView * success = [[UIAlertView alloc]
initWithTitle:#"New course added successfully"
message:#"You successfully added a new course"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles: nil];
[success show];
}else {
NSLog(#"Course not added");
}
}
Your IBAction keep it simple there you don't want to fire off life cycle event from an IBAction instead call the methods you need not to mention that it is not a good idea to call viewDidLoad before viewWillAppear Method...
- (IBAction)addNewCourse:(id)sender {
[self addCourse];
[self loadCourses];
}

first you check the array data it valid or not .(put break point and check it)
and i think u got error because u still not convert integer to string .
i replace this line in to tableview cellForRowAtIndexPath:
cell.detailTextLabel.text = dict[#"id"];
to replace
cell.detailTextLabel.text =[NSString stringWithFormat:#"%d",dict[#"id"]];
Its may be very helpful to you Thanks.

I think your problem is here.. your targeting AppDelegate as self.delegate
self.del = [[UIApplication sharedApplication] delegate];
And AppDelegate runs onetime at start of application only that's why your are getting error

Related

Getting delay to see next view controller ,see detail in post?

I have one login screen after that it will move to next view controller which have i have used some networks like http,json to get data from server. when i enter login username/password then if i click login button its getting delay to 8 seconds after that only it moving to next view controller.Still that my login screen alone showing for 8 seconds and then only it move to next view controller.
Here my login controller.m:
#implementation mainViewController
- (void)viewDidLoad {
[super viewDidLoad];
_username.delegate = self;
_password.delegate = self;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if (![defaults boolForKey:#"reg"]) {
NSLog(#"no user reg");
_logBtn.hidden = NO;
}
}
- (void)viewWillAppear:(BOOL)animated
{
[self.navigationController setNavigationBarHidden:YES animated:animated];
[super viewWillAppear:animated];
_username.text = nil;
_password.text = nil;
}
- (IBAction)LoginUser:(id)sender {
if ([_username.text isEqualToString:#"sat"] && [_password.text isEqualToString:#"123"]) {
NSLog(#"Login success");
[self performSegueWithIdentifier:#"nextscreen" sender:self];
}
else {
NSLog(#"login was unsucess");
// Alert message
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:#"wrong"
message:#"Message"
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *actionOk = [UIAlertAction actionWithTitle:#"Ok"
style:UIAlertActionStyleDefault
handler:nil];
[alertController addAction:actionOk];
[self presentViewController:alertController animated:YES completion:nil];
}
}
Here my nextcontroller.m
- (void)viewDidLoad {
[super viewDidLoad];
//for search label data
self.dataSourceForSearchResult = [NSArray new];
//collection of array to store value
titleArray = [NSMutableArray array];
// here only i am getting data from server
[self getdata];
self.collectionView.dataSource = self;
self.collectionView.delegate = self;
[self.collectionView reloadData];
}
Help me out. If my question din't understand.I can tell more about my post. And in my nextcontroller.m [self getdata] is i am getting data from server url.Thanks
My get data:
-(void)getdata {
NSString *userName = #“users”;
NSString *password = #“images”;
NSData *plainData = [password dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64String = [plainData base64EncodedStringWithOptions:0];
base64String=[self sha256HashFor: base64String];
NSString *urlString = #"https://porterblog/image/file”;
NSMutableURLRequest *request= [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:urlString]];
[request setHTTPMethod:#"GET"];
NSString *authStr = [NSString stringWithFormat:#"%#:%#", userName, base64String];
NSData *authData = [authStr dataUsingEncoding:NSUTF8StringEncoding];
NSString *authValue = [NSString stringWithFormat:#"Basic %#", [authData base64EncodedStringWithOptions:0]];
[request setValue:authValue forHTTPHeaderField:#"Authorization"];
NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSString *str = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding];
NSError * error;
self->arrayPDFName = [[NSMutableArray alloc]init];
NSDictionary *jsonResults = [NSJSONSerialization JSONObjectWithData:returnData options:NSJSONReadingMutableContainers error:nil];
NSDictionary *dictOriginal = jsonResults[#“birds”];
[titleArray addObject:[NSString stringWithFormat:#" birds(%#)”, dictOriginal[#"count"]]];
NSDictionary *dictOriginal2 = jsonResults[#"owl”];
[titleArray addObject:[NSString stringWithFormat:#" Owl(%#)”, dictOriginal2[#"count"]]];
NSDictionary *dictOriginal3 = jsonResults[#"pensq”];
[titleArray addObject:[NSString stringWithFormat:#" Pensq(%#)”, dictOriginal3[#"count"]]];
NSDictionary *dictOriginal4 = jsonResults[#“lion”];
[titleArray addObject:[NSString stringWithFormat:#" lion(%#)”, dictOriginal4[#"count"]]];
NSArray *arrayFiles = [NSArray arrayWithObjects: dictOriginal, dictOriginal2, dictOriginal3, dictOriginal4, nil];
NSLog(#"str: %#", titleArray);
for (NSDictionary *dict in arrayFiles) {
NSMutableArray *arr = [NSMutableArray array];
NSArray *a = dict[#"files"];
for(int i=0; i < a.count; i ++) {
NSString *strName = [NSString stringWithFormat:#"%#",[[dict[#"files"] objectAtIndex:i] valueForKey:#"name"]];
[arr addObject:strName];
}
[arrayPDFName addObject:arr];
}
NSString *errorDesc;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory1 = [paths objectAtIndex:0];
NSString *plistPath = [documentsDirectory1 stringByAppendingPathComponent:#"SampleData.plist"];
NSString *error1;
returnData = [ NSPropertyListSerialization dataWithPropertyList:jsonResults format:NSPropertyListXMLFormat_v1_0 options:0 error:&error];
if(returnData ) {
if ([returnData writeToFile:plistPath atomically:YES]) {
NSLog(#"Data successfully saved.");
}else {
NSLog(#"Did not managed to save NSData.");
}
}
else {
NSLog(#"%#",errorDesc);
}
NSDictionary *stringsDictionary = [NSDictionary dictionaryWithContentsOfFile:plistPath];
}
EDITED:
`- (void)viewDidLoad {
[super viewDidLoad];
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
self.dataSourceForSearchResult = [NSArray new];
titleArray = [NSMutableArray array];
//Background Tasks
[self getdata];
dispatch_async(dispatch_get_main_queue(), ^(void){
//Run UI Updates
self.collectionView.dataSource = self;
self.collectionView.delegate = self;
[self.collectionView reloadData];
self.navigationItem.hidesBackButton = YES;
});
});
}`
You're getting your data using main thread you need do to that in background then invoke the code you need (as i see is reload collectionView)
I assume that because you didn't show the getdata method code
If that the case you can use this code:
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
//Background Tasks
[self getdata];
dispatch_async(dispatch_get_main_queue(), ^(void){
//Run UI Updates
[self.collectionView reloadData];
});
});
It's mean that your VC will show immediately but the collectionView fill after you finish load the data, you can put some old data while loading like Facebook app (you see latest retrieved posts until finish loading].
Edit:
In your code you replace viewdidload method in nextController with next code:
- (void)viewDidLoad {
[super viewDidLoad];
//for search label data
self.dataSourceForSearchResult = [NSArray new];
//collection of array to store value
titleArray = [NSMutableArray array];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
//Background Tasks
[self getdata];
dispatch_async(dispatch_get_main_queue(), ^(void){
//Run UI Updates
[self.collectionView reloadData];
});
});
self.collectionView.dataSource = self;
self.collectionView.delegate = self;
}

Forward geocoding doesnt give correct results

I didn't get correct results for Forward geocoding in certain cases. When I search for some places or hotel it shows result of some others places or areas. I have got following code. I study the following link. What url should i place to get correct results.
how can we implement the following given in following site
https://developers.google.com/places/webservice/autocomplete
A request for addresses containing "Vict" with results in French:
https://maps.googleapis.com/maps/api/place/autocomplete/json?input=Vict&types=geocode&language=fr&key=API_KEY
A request for cities containing "Vict" with results in Brazilian
Portuguese:
https://maps.googleapis.com/maps/api/place/autocomplete/json?input=Vict&types=(cities)&language=pt_BR&key=API_KEY
I have implemented following but it doesn't give the results as i aspected
- (CLLocationCoordinate2D)addressLocation{
NSError *error = nil;
// NSString *lookUpString = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/geocode/json?address=%#&sensor=true", SearchtextField];
// NSString *API_KEY=#"AIzaSyB27SkGBzvEYKcxvZ5nmOVWvrA-6Xqf-7A";
NSString *API_KEY=#"AIzaSyCHcqJcqZbP1XpU-WB4VfRct5hpdgqisSY";
NSString *lookUpString = [NSString stringWithFormat:#"https://maps.googleapis.com/maps/api/geocode/json?address=%#&region=np&key=%#", SearchtextField,API_KEY];
lookUpString = [lookUpString stringByReplacingOccurrencesOfString:#" " withString:#"+"];
NSData *jsonResponse = [NSData dataWithContentsOfURL:[NSURL URLWithString:lookUpString]];
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:jsonResponse options:kNilOptions error:&error];
NSArray *locationArray = [[[jsonDict valueForKey:#"results"] valueForKey:#"geometry"] valueForKey:#"location"];
NSString *statusString = [jsonDict valueForKey:#"status"];
if ([statusString isEqualToString:#"OK"])
{
locationArray = [locationArray objectAtIndex:0];
Str_Latitude= [locationArray valueForKey:#"lat"];
Str_Longitude= [locationArray valueForKey:#"lng"];
NSLog(#"LatitudeString:%# & LongitudeString:%#", Str_Latitude, Str_Longitude);
/*Google place latitude Longitude*/
Arr_LatLong = #[Str_Latitude,Str_Longitude];
[[NSUserDefaults standardUserDefaults] setValue:Str_Latitude forKey:#"Str_Latitude"];
[[NSUserDefaults standardUserDefaults] setValue:Str_Longitude forKey:#"Str_Longitude"];
[[NSUserDefaults standardUserDefaults] synchronize];
GogLatitude = [Str_Latitude doubleValue];
Goglongitude = [Str_Longitude doubleValue];
if (Bool_SearchField) {
[self getGoogleAddress];
Bool_SearchField=FALSE;
}else{
}
}else{
UIAlertView *alertview =[[UIAlertView alloc] initWithTitle:#"Address not found" message:#"make sure you enter a valid address" delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alertview show];
NSLog(#"Something went wrong, couldn't find address");
[self.tableView reloadData];
}
GogLocation.latitude = GogLatitude;
GogLocation.longitude = Goglongitude;
return GogLocation;
}
When i search for radission in maps.google.com it shows as below
But when i search in my app it shows different locations then what I search
You can either take use of the Region Biasing, which according to wiki, should be NP. So add &region=np at the end of your query.
Or you can use the Viewport Biasing to set the bounds of your searches.
I have done what you have asked in one of my apps, but the url is different.
I am posting the function that gets called each time i input something in a text field.
-(void) startAutocomplete{
NSString* baseUrl = [NSString stringWithFormat:#"https://maps.googleapis.com/maps/api/place/queryautocomplete/json?input=%#&key=AIzaSyDz3HAmNY8NsgIhtA8gtbH-QA08Lg9tej4&types=all", self.locationTextfield.text];
NSURL *url = [NSURL URLWithString:[baseUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSLog(#"Url: %#", url);
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if (connectionError!=nil) {
[[[UIAlertView alloc] initWithTitle:nil message:connectionError.localizedDescription delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil] show ] ;
}else{
NSError *error = nil;
self.searchResult= [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
//NSLog(#"result:%#",self.searchResult);
[self.tableView reloadData];
}
}];
}

Unable to search in iTunes Store on iOS8

I'm using this code to open iTunes Store app and search for specific music:
NSString *iTunesLink = [NSString stringWithFormat:#"http://search.itunes.apple.com/WebObjects/MZSearch.woa/wa/search?entity=album&media=all&page=1&restrict=true&startIndex=0&term=TERM_NAME"];
NSURL *url = [NSURL URLWithString:iTunesLink];
[[UIApplication sharedApplication] openURL:url];
Code works fine on iOS7, by changing TERM_NAME value I can search whatever I want. The issue on iOS8 is that somehow search term is appended and prepended by ( " ) symbols. I'm using log to check what's the value of my NSURL but it looks fine.
This code worked for me:
NSString *artist = #"artist";
NSString *title = #"title";
NSOperationQueue *operationQueue = [NSOperationQueue new];
NSString *baseURLString = #"https://itunes.apple.com/search";
NSString *searchTerm = [NSString stringWithFormat:#"%# %#", artist, title];
NSString *searchUrlString = [NSString stringWithFormat:#"%#?media=music&entity=song&term=%#&artistTerm=%#&songTerm=%#", baseURLString, searchTerm, artist, title];
searchUrlString = [searchUrlString stringByReplacingOccurrencesOfString:#" " withString:#"+"];
searchUrlString = [searchUrlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *searchUrl = [NSURL URLWithString:searchUrlString];
NSURLRequest *request = [NSURLRequest requestWithURL:searchUrl];
[NSURLConnection sendAsynchronousRequest:request queue:operationQueue completionHandler:^(NSURLResponse* response, NSData* data, NSError* error)
{
if (error)
{
NSLog(#"Error: %#", error);
}
else
{
NSError *jsonError = nil;
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
if (jsonError)
{
NSLog(#"JSON Error: %#", jsonError);
}
else
{
NSArray *resultsArray = dict[#"results"];
if(resultsArray.count == 0)
{
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"917xfm" message:[NSString stringWithFormat:#"No results returned."] delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
[alert release];
});
}
else
{
NSDictionary *trackDict = resultsArray[0];
NSString *trackViewUrlString = trackDict[#"trackViewUrl"];
if (trackViewUrlString.length)
{
NSURL *trackViewUrl = [NSURL URLWithString:trackViewUrlString];
dispatch_async(dispatch_get_main_queue(), ^{
[[UIApplication sharedApplication] openURL:trackViewUrl];
});
}
}
}
}
}];

Get back data after Json parsing

In my iOS app I've to parse a JSON file. From this JSON I need the following stuff: name, image width and image height. To get image name I'ven't any problem, to get image with and height I use the following code:
- (void) loadImageFromWeb:(NSString *)urlImg forName:(NSString*)name {
NSURL* url = [NSURL URLWithString:urlImg];
//NSURLRequest* request = [NSURLRequest requestWithURL:url];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
NSString *authCredentials =#"reply:reply";
NSString *authValue = [NSString stringWithFormat:#"Basic %#",[authCredentials base64EncodedStringWithWrapWidth:0]];
[request setValue:authValue forHTTPHeaderField:#"Authorization"];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse * response,
NSData * data,
NSError * error) {
if (!error){
UIImage* image = [[UIImage alloc] initWithData:data];
imageWidth = image.size.width;
imageHeight = image.size.height;
imgWidth = [NSString stringWithFormat:#"%f", imageWidth];
imgHeight = [NSString stringWithFormat:#"%f", imageHeight];
self.dictWithDataForPSCollectionView = #{#"title": name,
#"width": imgWidth,
#"height": imgHeight};
[self.arrayWithData addObject:self.dictWithDataForPSCollectionView];
NSLog(#"DATA ARRAY: %#", self.arrayWithData);
} else {
NSLog(#"ERRORE: %#", error);
}
}];
}
You can see that I save the name, image width and image height in a NSDictionary then I put this in an NSMutableArray. When it execute the NSLog, I see this:
DATA ARRAY: (
{
height = "512.000000";
title = "Eau de Toilet";
width = "320.000000";
},
{
height = "1049.000000";
title = "Eau de Toilet";
width = "1405.000000";
}
)
My question is how to get this information back in the class who call my json parser, I tried to access to the variable in this way:
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
recivedData = [[NSMutableData alloc]init];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[recivedData appendData:data];
NSString *string = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"JSON: %#", string);
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSDictionary *json;
NSError *err;
json = [NSJSONSerialization JSONObjectWithData:recivedData options:NSJSONReadingMutableLeaves error:&err];
JsonCategoryReader *reader = [[JsonCategoryReader alloc]init];
[reader parseJson:json];
}
But when I run the code it shows me an empty array. How I can have the information in this class?
UPDATE:
The JSON I've to parse is the following:
{
"1":{
"entity_id":"1",
"type_id":"simple",
"sku":"EAU_DE_TOILET_1",
"description":"A passionate scent with the zest of exclusive Zegna Bergamot, sparked by Violettyne Captive, and the warmth of Vetiver and Cedarwood",
"short_description":"EAU DE TOILETTE NATURAL SPRAY",
"meta_keyword":null,
"name":"Eau de Toilet",
"meta_title":null,
"meta_description":null,
"regular_price_with_tax":60,
"regular_price_without_tax":60,
"final_price_with_tax":60,
"final_price_without_tax":60,
"is_saleable":true,
"image_url":"http:\/\/54.204.6.246\/magento8\/media\/catalog\/product\/cache\/0\/image\/9df78eab33525d08d6e5fb8d27136e95\/p\/r\/product_100ml.png"
},
"2":{
"entity_id":"2",
"type_id":"simple",
"sku":"EAU_DE_TOILET_2",
"description":"A passionate scent with the zest of exclusive Zegna Bergamot, sparked by Violettyne Captive, and the warmth of Vetiver and Cedarwood",
"short_description":"EAU DE TOILETTE NATURAL SPRAY",
"meta_keyword":null,
"name":"Eau de Toilet",
"meta_title":null,
"meta_description":null,
"regular_price_with_tax":60,
"regular_price_without_tax":60,
"final_price_with_tax":60,
"final_price_without_tax":60,
"is_saleable":true,
"image_url":"http:\/\/54.204.6.246\/magento8\/media\/catalog\/product\/cache\/0\/image\/9df78eab33525d08d6e5fb8d27136e95\/s\/c\/scheda_non_shop.jpg"
}
}
My method parseJson do the following:
- (void)parseJson:(NSDictionary *)jsonDict {
// Controllo che il json sia stato ricevuto
if (jsonDict) {
self.nameArray = [[NSMutableArray alloc]init];
self.imgUrlArray = [[NSMutableArray alloc]init];
self.dictWithDataForPSCollectionView = [[NSDictionary alloc]init];
self.arrayWithData = [[NSMutableArray alloc]init];
[self createArrayWithJson:jsonDict andIndex:1];
[self createArrayWithJson:jsonDict andIndex:2];
}
- (void)createArrayWithJson:(NSDictionary*)json andIndex:(NSString*)i {
NSDictionary *products = [json objectForKey:i];
NSString *name = [products objectForKey:#"name"];
NSString *imgUrl = [products objectForKey:#"image_url"];
// Scarico l'immagine e calcolo le dimensioni
if (name != nil && imgUrl != nil) {
[self loadImageFromWeb:imgUrl forName:name];
}
}
I hope you understand what I did
what happen is that your class is make before that your json is download, for have a good sequence you have to call your method for parse the json inside the completionHandler block, when you are sure that it is download. then when you have your object load you can parse it like this example:
for (NSDictionary *dic in reader.arrayWithData){
NSLog("height: %#",[dic objectForKey:#"height"]);
NSLog("title: %#",[dic objectForKey:#"title"]);
NSLog("width: %#",[dic objectForKey:#"width"]);
}

iOS JSON parsing from web to a UITableView

I'm experiencing a problem with my code but I'm not sure why it's doing this. It's just giving me an error saying JSON Error. The UITableView never gets filled with anything. I'm not very experienced with iOS, so any help is appreciated.
//
// ViewController.m
// Westmount Procrastinator
//
// Created by Saleem on 10/25/13.
// Copyright (c) 2013 Saleem Al-Zanoon. All rights reserved.
//
#import "ViewController.h"
#interface ViewController ()
#property (strong, nonatomic) IBOutlet UIWebView *webView;
#property (strong, nonatomic) IBOutlet UITableView *tableView;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSString *fullURL = #"********";
NSURL *url2 = [NSURL URLWithString:fullURL];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url2];
[_webView loadRequest:requestObj];
self.title = #"News";
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSURL *url = [NSURL URLWithString:#"****************"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection connectionWithRequest:request delegate:self]; // NSString * urlString = [NSString stringWithFormat:#"http://salespharma.net/westmount/get_all_products.php"];
// NSURL * url = [NSURL URLWithString:urlString];
// NSData * data = [NSData dataWithContentsOfURL:url];
// NSError * error;
// NSMutableDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
// NSLog(#"%#",json);
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
data = [[NSMutableData alloc] init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)theData
{
[data appendData:theData];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
NSArray *responseDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:NULL];
//news = [responseDict objectAtIndex:0];
// [mainTableView reloadData];
if ([responseDict isKindOfClass:[NSArray class]]) {
news = responseDict;
[mainTableView reloadData];
} else {
// Looks like here is some part of the problem but I don't know why.
NSLog(#"JSON Error.");
UIAlertView *errorView = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Could not contact server!" delegate:nil cancelButtonTitle:#"Dismiss" otherButtonTitles:nil];
[errorView show];
}
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
UIAlertView *errorView = [[UIAlertView alloc] initWithTitle:#"Error" message:#"The download could not complete - please make sure you're connected to either 3G or Wi-Fi." delegate:nil cancelButtonTitle:#"Dismiss" otherButtonTitles:nil];
[errorView show];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
- (int)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (int)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [news count];
}
NSString *_getString(id obj)
{
return [obj isKindOfClass:[NSString class]] ? obj : nil;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if(cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"Cell"];
}
cell.textLabel.text = _getString([[news objectAtIndex:indexPath.row] objectForKey:#"Issue"]);
cell.detailTextLabel.text = _getString([[news objectAtIndex:indexPath.row] objectForKey:#"Name"]);
return cell;
}
#end
How the JSON looks on the internet:
{
"Issues":[
{
"Issue":"2",
"Link":"google.com",
"Name":"Ios Test"
},
{
"Issue":"3",
"Link":"Yahoo",
"Name":"iOS test 2"
}
],
"success":1
}
Edit: sorry for not being clear in my question, The app does not crash but fails to load the data into the database in the log it puts this up:
2013-10-26 10:26:41.670 Westmount Procrastinator[2490:70b] JSON Error.
2013-10-26 10:26:41.671 Westmount Procrastinator[2490:70b] Server Data:
{"Issues":[{"Issue":"2","Link":"google.com","Name":"Ios Test"}],"success":1}
The goal of the application to contact a database download a list of Issues of a newspaper then list them in the list view.. Then allowing the user to click on the issues and download them.
Edit I added more to the JSON to help explain.
From your sample JSON structure it does not appear to be a NSArray. It is NSDictionary instead. So, while you are parsing JSON data save it in NSDictionary and not in NSArray. Also, change your IF condition afterwards.
Importantly, if your tableview is reading data from an NSArray of NSDictionaries then I would say put this NSDictionary into an NSArray and pass it to table view. Also, check from server side what is the output in case they are multiple dictionaries in which you need to handle accordingly. So essentially there are couple of more lines you need to induce here or else ask data provider (server side) to send NSArray in all cases.
NSDictionary *responseDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:NULL];
if ([responseDict isKindOfClass:[NSDictionary class]]) {
NSArray *tableArray = [NSArray arrayWithArray:responseDict[#"Issues"]];
}
Now use tableArray to populate your table.
Issues is an array of dictionaries, so you should ask for the dictionary at the indexpath.row, then use objectForKey to pull the appropriate value from that dictionary.
NSDictionary *myDict = #{#"Issues": #[#{#"Issue": #"2",
#"Link": #"google.com",
#"Name": #"Ios Test"},
#{#"Issue": #"3",
#"Link": #"Yahoo",
#"Name": #"iOS test 2"}],
#"success": #"1"};
NSArray *issues = [myDict objectForKey:#"Issues"];
[issues enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSLog(#"Issue: %# Link: %# Name: %#", [obj objectForKey:#"Issue"], [obj objectForKey:#"Link"], [obj objectForKey:#"Name"]);
}];
Will return:
2013-10-26 16:42:43.572 Jsontest[43803:303] Issue: 2 Link: google.com Name: Ios Test
2013-10-26 16:42:43.573 Jsontest[43803:303] Issue: 3 Link: Yahoo Name: iOS test 2

Resources