I create one application and I read many data in table View from JSON and I want parsed this JSON and store in sqlite but I dont know from where should I start?
this is parsed my json code :
#implementation TableViewController
{
NSArray *news;
NSMutableData *data;
NSString *title;
NSMutableArray *all;
}
#synthesize mainTable;
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"News";
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSURL *url = [NSURL URLWithString:#"http://zacandcatie.com/YouTube/json.php"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLConnection *con = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[con start];
}
- (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;
news = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
for (int i =0; i < [news count]; i++)
{
NSIndexPath *indexPath = [self.mainTable indexPathForSelectedRow];
title =[[news objectAtIndex:indexPath.row+i]objectForKey:#"title"];
if (!all) {
all = [NSMutableArray array];
}
[all addObject:title];
}
NSLog(#"%#",all);
[mainTable reloadData];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
UIAlertView *errorView = [[UIAlertView alloc]initWithTitle:#"Error" message:#"The Connection has been LOST" delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
[errorView show];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
you my json url. I want store "title"&"date_string" value in sqlite.
please guide me!!!
After parsing you data in the form of NSDictionary you can create a query of insert into and fire the query n your data will be save into your database
-(void)InsertRecords:(NSMutableDictionary *)dict
{
sqlite3_stmt *stmt;
sqlite3 *cruddb;
NSMutableString *str = [NSMutableString stringWithFormat:#"Insert into tblName ("];
for (int i = 0; i<[[dict allKeys] count]; i++)
{
[str appendFormat:#"%#,",[[dict allKeys] objectAtIndex:i]];
}
[str appendFormat:#")values ("];
for (int i = 0; i<[[dict allKeys] count]; i++)
{
[str appendFormat:#"%#,",[dict valueForKey:[[dict allKeys] objectAtIndex:i]]];
}
[str appendFormat:#");"];
NSLog(#"qry : %#",str);
const char *sql = [str UTF8String]; ;
if((sqlite3_open([database UTF8String], &cruddb)==SQLITE_OK))
{
if (sqlite3_prepare(database, sql, -1, &stmt, NULL) ==SQLITE_OK)
{
sqlite3_step(stmt);
sqlite3_finalize(stmt);
}
else
{
NSLog(#"Problem with prepare statement: %s", sqlite3_errmsg(database));
}
sqlite3_close(database);
}
else
{
NSLog(#"An error has occured: %s",sqlite3_errmsg(database));
}
}
Try this.
Continuing #Divz Ans...
you will have create the .sqlite file. And there is nothing easier than this.
There are two ways(that i know) to create sqlite file,
1> you can download SQLite Manager add-on in firefox, where you can manipulate data in database graphically.
Or,
2> you can use Terminal with a single line command, sqlite3 dbFileName.sqlite. enter,
where you will get sqlite> now start with further SQL(create/insert/update..) queries.
you can find your sqlite file at MacHD>users>admin(not shared one)>yourFile.sqlite or, finder---go>home>yourFile.sqlite
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
db=[[SKDatabase alloc]initWithFile:#"student.sqlite"];
NSURL *url=[NSURL URLWithString:#"..........Your Url............"];
NSURLRequest *json_request=[[NSURLRequest alloc]initWithURL:url];
NSData *data=[NSURLConnection sendSynchronousRequest:json_request returningResponse:nil error:nil];
NSMutableDictionary *dic=[NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSMutableArray *student_ary=[dic objectForKey:#"students"];
for (NSMutableArray *student_info in student_ary) {
NSMutableDictionary *insert=[[NSMutableDictionary alloc]initWithCapacity:2];
NSMutableDictionary *info=[student_info mutableCopy];
[insert setObject:[info objectForKey:#"name"] forKey:#"name"];
[insert setObject:[info objectForKey:#"city"] forKey:#"city"];
[db insertDictionary:insert forTable:#"student_info"];
}
})
//.m file view....
-(void)viewDidAppear:(BOOL)animated
{
NSString *qry=#"select * from student_info";
ary=[[db lookupAllForSQL:qry] mutableCopy];
[tableView reloadData];
}
You can do some thing like this :
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// tableview cell setup
NSArray* keys = [self.data allKeys];
cell.textLabel.text = [self.data objectForKey:[keys objectAtIndex:indexPath.row]];
return cell;
}
Please refer this links to have data in order in dictionary
NSDictionary with ordered keys
Related
I need to display particular object for key(currency) using post method after getting response from web.
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController{
NSMutableData *mutableData;
NSMutableString *arr;
#define URL #"website"
// change this URL
#define NO_CONNECTION #"No Connection"
#define NO_VALUES #"Please enter parameter values"
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
-(IBAction)sendDataUsingPost:(id)sender{
[self sendDataToServer :#"POST"];
}
-(IBAction)sendDataUsingGet:(id)sender{
[self sendDataToServer : #"GET"];
}
-(void) sendDataToServer : (NSString *) method{
NSString *Branchid=#"3";
serverResponse.text = #"Getting response from server...";
NSURL *url = nil;
NSMutableURLRequest *request = nil;
if([method isEqualToString:#"GET"]){
NSString *getURL = [NSString stringWithFormat:#"%#?branch_id=%#", URL, Branchid];
url = [NSURL URLWithString: getURL];
request = [NSMutableURLRequest requestWithURL:url];
NSLog(#"%#",getURL);
}else{ // POST
NSString *parameter = [NSString stringWithFormat:#"branch_id=%#",Branchid];
NSData *parameterData = [parameter dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
url = [NSURL URLWithString: URL];
NSLog(#"%#", parameterData);
request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPBody:parameterData];
arr= [NSMutableString stringWithUTF8String:[parameterData bytes]];
NSLog(#"responseData: %#", arr);
//NSLog(#"%#",[[arr valueForKey:#"BranchByList"]objectForKey:#"currency"]);
}
[request setHTTPMethod:method];
[request addValue: #"application/x-www-form-urlencoded; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
//NSLog(#"%#",[connection valueForKeyPath:#"BranchByList.currency"]);
if( connection )
{
mutableData = [NSMutableData new];
//NSLog(#"%#",[connection valueForKeyPath:#"BranchByList.currency"]);
}
}
-(void) connection:(NSURLConnection *) connection didReceiveResponse:(NSURLResponse *)response
{
[mutableData setLength:0];
}
-(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[mutableData appendData:data];
}
-(void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
serverResponse.text = NO_CONNECTION;
return;
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSMutableString *responseStringWithEncoded = [[NSMutableString alloc] initWithData: mutableData encoding:NSUTF8StringEncoding];
//NSLog(#"Response from Server : %#", responseStringWithEncoded);
NSLog(#"%#",responseStringWithEncoded );
NSLog(#"%#",[responseStringWithEncoded valueForKeyPath:#"BranchByList.currency"] );
NSAttributedString * attrStr = [[NSAttributedString alloc] initWithData:[responseStringWithEncoded dataUsingEncoding:NSUnicodeStringEncoding] options:#{ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType } documentAttributes:nil error:nil];
serverResponse.attributedText = attrStr;
// NSLog(#"%#",attrStr);
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
i got response branch_id=3 but i want to show to "currency" but i tried lot but failure.
my response like this I need to display only currency.....
Response from Server :
{"BranchByList":
[
{"id":"342","flag_image":"http:\/\/demo.techzarinfo.com\/newantara\/images\/flags\/USD.png","units":"1","code":"USD B","currency":"US DOLLAR BIG","buy":"4.36","sell":"4.395","updated":"2016-04-11 03:24:24"
},
{"id":"342","flag_image":"http:\/\/demo.techzarinfo.com\/newantara\/images\/flags\/USD.png","units":"1","code":"USD B","currency":"US DOLLAR BIG","buy":"4.36","sell":"4.395","updated":"2016-04-11 03:24:24"
}
]};
Your response structure is:
-Dictionary
--Array
---Dictionary Objects
You need to convert your Data into NSDictionary to parse it.
Following code will do that for you:
NSError* error;
NSDictionary* json = [NSJSONSerialization JSONObjectWithData: mutableData
options:kNilOptions
error:&error]; //Now we got top level dictionary
NSArray* responseArray = [json objectForKey:#"BranchByList"]; //Now we got mid level response array
//Get Embeded objects from response Array:
NSDictionary *priceDic = [responseArray objectAtIndex:0]; //Getting first object since you arent telling what the second object is for
NSString *buyingPrice = [priceDic objectForKey: #"buy"]; //Buying price
NSString *sellingPrice = [priceDic objectForKey:#"sell"]; //Selling price
NSString *currency = [priceDic objectForKey:#"currency"]; //Currency
Though this is only sticking to the point and getting the job done.
Proper way to get the job done would be to create a model class for response. Create a class inherited from NSObject and use it as model for this response. Add a initWithDic: method to that class, Pass it your response dic as parameter and delegate all this dictionary parsing to that method.
Also, NSURLConnection is deprecated since iOS 9.0. You should use NSURLSession instead.
Try This May be it will help you:-
NSString *str=[[NSString alloc]initWithData:responseData encoding:NSUTF8StringEncoding];
NSLog(#"str : %#",str);
NSDictionary *dict6 = [self cleanJsonToObject:responseData];
NSLog(#"str : %#",dict6);
NSMArray *array1 = [dict6 objectForKey:#"BranchByList"];
NSLog(#"DICT : %#",array1);
NSDictionary *Dict3 = [array1 objectAtIndex:0];
NSString *Str1 = [dict3 objectForKey:#"currency"];
NSLog(#"Str1 : %#",Str1);
- (id)cleanJsonToObject:(id)data
{
NSError* error;
if (data == (id)[NSNull null])
{
return [[NSObject alloc] init];
}
id jsonObject;
if ([data isKindOfClass:[NSData class]])
{
jsonObject = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
} else
{
jsonObject = data;
}
if ([jsonObject isKindOfClass:[NSArray class]])
{
NSMutableArray *array = [jsonObject mutableCopy];
for (int i = (int)array.count-1; i >= 0; i--)
{
id a = array[i];
if (a == (id)[NSNull null])
{
[array removeObjectAtIndex:i];
} else
{
array[i] = [self cleanJsonToObject:a];
}
}
return array;
} else if ([jsonObject isKindOfClass:[NSDictionary class]])
{
NSMutableDictionary *dictionary = [jsonObject mutableCopy];
for(NSString *key in [dictionary allKeys])
{
id d = dictionary[key];
if (d == (id)[NSNull null])
{
dictionary[key] = #"";
} else
{
dictionary[key] = [self cleanJsonToObject:d];
}
}
return dictionary;
} else
{
return jsonObject;
}
}
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;
}
The app keeps score during a game. Based off of your score, it will retrieve a quote from an online database, using a GET method and returning it in JSON format. For example, your score is 5, you get 1 quote, 10, you get 2 and so on. The view that shows the quote(s) is a UIViewController with a UITextView in it.
I have a for loop that runs based off the score, to run the same GET request over and over again, after a 1.5 second delay so the server housing the database won't reject requests made nearly simultaneously.
I create a few NSStrings and pull information from the JSON data, append it into some basic HTML code and then set that as the UITextView attributedText.
Most of the time this runs great, but every once in a while, I'll expect 2 quotes, and only get 1, or some of the quotes will wind up being the same.
Can someone tell me if there is a better way to go about doing this than how I currently am?
- (void)viewWillAppear:(BOOL)animated {
if ([textView.text isEqualToString:#""]) {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSInteger getReady = [defaults integerForKey:#"after"];
self.theNumber = getReady;
for(int i = 0; i< self.theNumber; i++) {
[self performSelector:#selector(quoteView) withObject:self afterDelay:1.5 ];
}
}
}
-(void) quoteView {
NSString *bringitalltogether = #"http://url.com&type=json";
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:bringitalltogether]
cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:60];
[request setHTTPMethod:#"GET"];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection start];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
if ([response isKindOfClass:[NSHTTPURLResponse class]])
{
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*) response;
if (code == 200){
}
else
{
UIAlertView *oops = [[UIAlertView alloc] initWithTitle:#"Oops" message:#"The network is having difficulties getting you the quote. Please check your network settings and try again later." delegate:self cancelButtonTitle:#"Ok" otherButtonTitles: nil];
[oops show];
}
}
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSMutableDictionary *allResults = [NSJSONSerialization
JSONObjectWithData:data
options:NSJSONReadingAllowFragments
error:nil];
NSArray *book = [allResults valueForKey:#"bookname"];
self.bookstring = [book objectAtIndex:0];
NSArray *chapter = [allResults valueForKey:#"chapter"];
self.chapterstring = [chapter objectAtIndex:0];
NSArray *verse = [allResults valueForKey:#"verse"];
self.versestring = [verse objectAtIndex:0];
NSArray *text = [allResults valueForKey:#"text"];
self.textstring = [text objectAtIndex:0];
[self doneGotIt];
}
- (void) doneGotIt {
if (!self.theArray) {
self.theArray = [[NSMutableArray alloc] init];
}
NSString *doIt = [NSString stringWithFormat:#"%# - %# %#:%#", self.textstring, self.bookstring, self.chapterstring, self.versestring];
[self.theArray addObject:doIt];
NSString *theEnd = [self.theArray componentsJoinedByString:#"\n"];
NSString *loadHTML = [#"<head> <style type='text/css'>a > img {pointer-events: none;cursor: default;}</style></head><b><div align=\"left\"><font size=5>" stringByAppendingString:theEnd];
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithData:[loadHTML dataUsingEncoding:NSUnicodeStringEncoding] options:#{ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType } documentAttributes:nil error:nil];
textView.attributedText = attributedString;
NSLog(#"ARRAY: %#", self.theArray);
NSLog(#"String: %#", theEnd);
}
-(IBAction)finished {
[self dismissViewControllerAnimated:YES completion:nil];
textView = nil;
}
From the NSLogs I have towards the end there, sometimes the NSMutableArray contains several of the same quotes, which is why they don't show in the string, because it eliminates duplicates. My question is if there is a better way to do this that will keep these errors from occurring?
Here is some pseudo code for you
mutableArray = new NSMutableArray
while([mutableArray count] < total) {
quote = getQuote()
if([array indexOfObject:quote] != NSNotFound)
[mutableArray addObject:quote]
}
This will ensure you do not have duplicate quotes. After you have an array of valid quotes, you can then construct the string exactly how you want it.
In my app I'm starting NSURLConnection, parsing XML, initialize array from this XML, and show it in the tableView. In ViewDidLoad I appeal to the server with a query parameter 0 , and it's returned for me string, after all conversion a have in tableView 4 rows - titles, and when i push on some of this titles, all process (connection to the server, parsing, arrays initialising, ) must be repeated. In didSelectedRowAtIndexPath I have to transmit section ID (so that the server sent me the correct data). How can I do it correctly? I'm establish connection in ViewDidLoad, how can I call it again?
My .m file:
#import "catalogViewController.h"
#import "XMLReader.h"
#interface catalogViewController ()
#end
#implementation catalogViewController
- (id)initWithStyle:(UITableViewStyle)style {
self = [super initWithStyle:style];
if (self) { } return self;
}
//-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-CONNECTIONS METHOD START-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[_receivedData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[_receivedData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
[connection release];
[_receivedData release];
NSString *errorString = [[NSString alloc] initWithFormat:#"Connection failed! Error - %# %# %#", [error localizedDescription], [error description], [[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]]; NSLog(#"%#",errorString);
[errorString release];
}
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-GET FULL DATA HERE-=-=-=-=-=-=-=-=--=-=-=-=-=-=-
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSString *dataString = [[NSString alloc] initWithData:_receivedData encoding:NSUTF8StringEncoding];
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-XMLPARSER PART START-=-=-=-=-=-=-=-=-=-=-=-=-=-=- //
NSString *testXMLString = [NSString stringWithContentsOfURL:myURL usedEncoding:nil error:nil];
// -=-=-=-=-=-=-=-=-=-=Parse the XML into a dictionary-=-=-=-=-=-=-=-=-=-=
NSError *parseError = nil;
_xmlDictionary = [XMLReader dictionaryForXMLString:testXMLString error:&parseError];
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-XMLPARSER PART END-=-=-=-=-=-=-=
_titleArr = [[NSArray alloc] initWithArray:[[[_xmlDictionary objectForKey:#"result"] objectForKey:#"name"] valueForKey:#"text"]];
_IDArr = [[NSArray alloc] [[[_xmlDictionary objectForKey:#"result"] objectForKey:#"id"] valueForKey:#"text"]];
_priceArr= [[NSArray alloc][[[_xmlDictionary objectForKey:#"result"] objectForKey:#"price"] valueForKey:#"text"]];
_ImageURLArr=[[NSArray alloc][[[_xmlDictionary objectForKey:#"result"] objectForKey:#"img"] valueForKey:#"text"]];
[connection release];
[_receivedData release];
[dataString release];
_didDataLoaded=TRUE;
[_myTableView reloadData]; // IBOutlet property
[self.tableView reloadData]; //default
}
//-=-=-=-=-=-=-=-=-=-=-Connection methods END-=-=-=-=-=-=-=-=-=-
- (void)viewDidLoad {
[super viewDidLoad];
_didDataLoaded=FALSE;
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-XMLPARSER PART START-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//-=-==-=-=-=-=-=-=-=-=-=-=--=-=START Shit with connection-=-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=
NSString* params = #"request_params";
NSURL* url = [NSURL URLWithString:#"my URL"];
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:15.0];
[request addValue:#"text/xml; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
request.HTTPMethod = #"POST";
request.HTTPBody = [params dataUsingEncoding:NSUTF8StringEncoding];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
if (connection) {
NSLog(#"Connecting...");
_receivedData = [[NSMutableData data] retain];
} else {
NSLog(#"Connecting error");
}
}
//-=-==-=-=--=-==-=-=-=-=-=--=-==---=-=--==-=-=-=-=-TableView methods-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=--=-=-=-=-=-=-=
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (_didDataLoaded == FALSE) {
return 1;
}
else return self.titleArr.count;
}
-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView { return 1; }
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"creatures"];
UIImage *creatureImage = nil;
if (_didDataLoaded == FALSE) {
cell.textLabel.text=#"Downloading...";
cell.detailTextLabel.text= #"downloading...";
} else {
cell.textLabel.text = [self.titleArr objectAtIndex:indexPath.row];
cell.detailTextLabel.text= _IDArr[indexPath.row];
NSString *img = self.ImageURLArr[indexPath.row];
creatureImage =[[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:img]]]; cell.imageView.image = creatureImage;
}
return cell;
}
#end
You can move the relevant code from viewDidLoad to a specific method, something like:
- (void)loadXMLData {
// Initiate your loading/parsing
}
In viewDidLoad just call this method:
- (void)viewDidLoad {
[super viewDidLoad];
[self loadXMLData];
}
This way you can call [self loadXMLData] multiple times.
However... be careful with calling [tableView reloadData] from inside a UITableViewDelegate method implementation, as this will cause the tableview to call (at least some of the) delegate methods, which can cause recursive loops or other odd behaviour.
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