I am new in iOS developing. In my project I have taken a tableView and a search bar. Now when I am searching one of the datas of my tableview, no search results are coming. Can anyone please solve my problem?
Any help will be appreciated. Thanks in advance.
This is my ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property(strong, nonatomic) NSMutableData *postData;
#property(nonatomic, strong)NSArray *arrDetail;
#property(nonatomic, strong)NSArray *searchResults;
#property (weak, nonatomic) IBOutlet UITableView *parserTable;
#property (strong, nonatomic) IBOutlet UIActivityIndicatorView *mySpinner;
#end
This is my ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_mySpinner.hidden = NO;
[self fetchData];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (BOOL)prefersStatusBarHidden {
return YES;
}
- (void) fetchData {
[_mySpinner startAnimating];
NSString *post = [NSString stringWithFormat:#"test=Message&this=isNotReal"];
_postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%d", [_postData length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:#"http://svn.indusnettechnologies.com/HHC/webservice/users/countrylist?apiKey=hgfyhfyi87hgc67"]];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setHTTPBody:_postData];
NSURLResponse *requestResponse;
NSData *requestHandler = [NSURLConnection sendSynchronousRequest:request returningResponse:&requestResponse error:nil];
NSString *requestReply = [[NSString alloc] initWithBytes:[requestHandler bytes] length:[requestHandler length] encoding:NSASCIIStringEncoding];
NSLog(#"requestReply: %#", requestReply);
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
if (conn) {
_postData = [NSMutableData data];
}
else{
//error
}
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
// A response has been received, this is where we initialize the instance var you created
// so that we can append data to it in the didReceiveData method
// Furthermore, this method is called each time there is a redirect so reinitializing it
// also serves to clear it
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
// Append the new data to the instance variable you declared
[_postData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
// The request is complete and data has been received
// You can parse the stuff in your instance variable now
// self.data parse
NSDictionary *dict= [NSJSONSerialization JSONObjectWithData:self.postData options:kNilOptions error:nil];
self.arrDetail = [dict valueForKey:#"Countries"];
[self.mySpinner stopAnimating];
self.mySpinner.hidden = YES;
[self.parserTable reloadData];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
// The request has failed for some reason!
// Check the error var
}
#pragma mark Table View Delegates
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"tableCell"];
UILabel *lbl1 = (UILabel*)[cell.contentView viewWithTag:2];
lbl1.text = [[self.arrDetail objectAtIndex:indexPath.row]valueForKey:#"CountryCode"];
UILabel *lbl2 = (UILabel*)[cell.contentView viewWithTag:1];
lbl2.text = [[self.arrDetail objectAtIndex:indexPath.row]valueForKey:#"CountryName"];
UILabel *lbl3 = (UILabel*)[cell.contentView viewWithTag:3];
lbl3.text = [NSString stringWithFormat:#"%d.", indexPath.row];
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
//return [self.arrDetail count];
if (tableView == self.searchDisplayController.searchResultsTableView) {
return [_searchResults count];
} else {
return [_arrDetail count];
}
}
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSPredicate *resultPredicate = [NSPredicate
predicateWithFormat:#"SELF contains[cd] %#",
searchText];
_searchResults = [_arrDetail filteredArrayUsingPredicate:resultPredicate];
}
#pragma mark - UISearchDisplayController delegate methods
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller
shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString
scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
objectAtIndex:[self.searchDisplayController.searchBar
selectedScopeButtonIndex]]];
return YES;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Change following method like I have done:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"tableCell"];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSMutableDictionary * tempDict;
if (tableView == self.searchDisplayController.searchResultsTableView)
{
tempDict = [_searchResults objectAtIndex:indexPath.row];
}
else
{
tempDict = [_arrDetail objectAtIndex:indexPath.row];
}
UILabel *lbl1 = (UILabel*)[cell.contentView viewWithTag:2];
lbl1.text = [tempDict valueForKey:#"CountryCode"];
UILabel *lbl2 = (UILabel*)[cell.contentView viewWithTag:1];
lbl2.text = [tempDict valueForKey:#"CountryName"];
UILabel *lbl3 = (UILabel*)[cell.contentView viewWithTag:3];
lbl3.text = [NSString stringWithFormat:#"%d.", indexPath.row];
return cell;
}
Problem is also in your predicate. change it
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
//country_name and country_code are keys in your dictionary of country
NSPredicate *p1 = [NSPredicate predicateWithFormat:#"country_name contains[cd] %#", searchText];
NSPredicate *p2 = [NSPredicate predicateWithFormat:#"country_code contains[cd] %#", searchText];
NSPredicate *resultPredicate = [NSCompoundPredicate orPredicateWithSubpredicates: #[p1, p2]];
_searchResults = [_arrDetail filteredArrayUsingPredicate:resultPredicate];
}
Related
I’m using searchbarcontroller for filter the tableview data, everything is working fine but the problem is same data is repeating on filter while using searchbarcontroller tableview.
Like: suppose if List of alphabets is showing on the tableview (A,B,C,D) tableViewCells then when i used searchbarcontroller on this tableview then (tableView == self.searchDisplayController.searchResultsTableView) is shows the data in repeating way
Like: if i'm search for A the searchResultTableView is showing (A,A,A,A,A,A) on tableViewCells.
But on the normal tableview data is showing normally without repeating the data.
Any one please suggest me where is the actual problem in my code.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
NSURLRequest *request=[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.xyz.com/work.php]];
responseDataSP=[[NSMutableData alloc]init];
urlConnectionSP=[[NSURLConnection alloc]initWithRequest:request delegate:self];
NSLog(#"nsurl my %#",urlConnectionSP);
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
NSLog(#"Error");
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
[responseDataSP setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
[responseDataSP appendData:data];
NSLog(#"%#",responseDataSP);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSError *error=nil;
NSDictionary *dicSP=[NSJSONSerialization JSONObjectWithData:responseDataSP options:NSJSONReadingMutableContainers error:&error];
self.totalDataSP=[dicSP objectForKey:#"data"];
NSLog(#"%#",_totalDataSP);
totalTitleSP=[[NSMutableArray alloc]init];
totalImageSP=[[NSMutableArray alloc]init];
totalIdWalaSP=[[NSMutableArray alloc]init];
[_tableView reloadData];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
return [searchResults count];
} else {
return [_totalDataSP count];
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 80;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SkillsTableCell";
SkillsTableCell *cell = (SkillsTableCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"SkillsTableCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
NSDictionary *items=nil;
NSArray *titleSP;
NSArray *imageSP;
NSArray *idwalaSP;
for(int i=0;i<[_totalDataSP count];i++){
// NSLog(#"the _totalDataSP is %#",[_totalDataSP count]);
items=[_totalDataSP objectAtIndex:i];
titleSP=[items objectForKey:#"first_name"];
[totalTitleSP addObject:titleSP];
imageSP=[items objectForKey:#"profile_pic"];
[totalImageSP addObject:imageSP];
idwalaSP=[items objectForKey:#"id"];
[totalIdWalaSP addObject:idwalaSP];
category_id = [items objectForKey:#"id"];
NSLog(#"id value is %#",category_id);
}
dispatch_async(dispatch_get_main_queue(), ^{
if (tableView == self.searchDisplayController.searchResultsTableView) {
cell.textLabel.text = [searchResults objectAtIndex:indexPath.row];
} else {
cell.nameLabel.text=[totalTitleSP objectAtIndex:indexPath.row];
}
//For Image
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:[totalImageSP objectAtIndex:indexPath.row]]];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (data) {
cell.thumbnailImageView.image = [UIImage imageWithData:data];
}
}];
[cell setNeedsDisplay];
});
return cell;
}
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSPredicate *resultPredicate = [NSPredicate
predicateWithFormat:#"SELF contains[cd] %#",
searchText];
searchResults = [totalTitleSP filteredArrayUsingPredicate:resultPredicate];
}
#pragma mark - UISearchDisplayController delegate methods
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller
shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString
scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
objectAtIndex:[self.searchDisplayController.searchBar
selectedScopeButtonIndex]]];
return YES;
}
Thanks In Advance.
Using Predicates with Arrays
NSPredicate *sPredicate = [NSPredicate predicateWithFormat:#"SELF contains[c] 'e'"];
[array filterUsingPredicate:sPredicate];
or
It display desire order without duplicates
NSArray *beginArray = [filteredArray filteredArrayUsingPredicate:
[NSPredicate predicateWithFormat:
#"self BEGINSWITH[cd] %#", searchText]];
NSArray *anyArray = [filteredArray filteredArrayUsingPredicate:
[NSPredicate predicateWithFormat:
#"self CONTAINS[cd] %#", searchText]];
NSMutableArray *resultArray = [NSMutableArray arrayWithArray:beginArray];
for (id obj in anyArray) {
if (![resultArray containsObject:id]) {
[resultArray addObject:id];
}
}
filteredArray = resultArray;
Doing JSON work in my iPhone app, trying to list the json in a tableview, the json can be found here: appwhittle.com/api/db_all.php
I need this json to work with both android and ios, since i made the android app first it works without problem on the android device, but i cant seem to figure out what is wrong.
SearchViewController.m:
//
// SearchViewController.m
// Night Locations
//
// Created by Stian Wiik Instebø on 12/9/13.
// Copyright (c) 2013 Stian Wiik Instebø. All rights reserved.
//
#import "SearchViewController.h"
#import "SBJson4.h"
#interface SearchViewController ()
#end
#implementation SearchViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.title = #"Search for location";
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSURL *url = [NSURL URLWithString:#"http://appwhittle.com/api/db_all.php"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
}
- (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:0 error:nil];
[mainTableView reloadData];
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
UIAlertView *errorView = [[UIAlertView alloc] initWithTitle:#"Error" message:#"The download could not complete" delegate:nil cancelButtonTitle:#"Dismiss" otherButtonTitles:nil, nil];
[errorView show];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
- (int)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (int)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [news count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MainCell"];
if (cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"MainCell"];
}
[cell release];
cell.textLabel.text = [[news objectAtIndex:indexPath.row] objectForKey:#"name"];
return cell;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
SearchViewController.h:
#import <UIKit/UIKit.h>
#interface SearchViewController : UIViewController {
IBOutlet UITableView *mainTableView;
NSArray *news;
NSMutableData *data;
}
#end
The error appears at the line: cell.textLabel.text = [[news objectAtIndex:indexPath.row] objectForKey:#"name"]; where i get the title into one of the rows in the tableView.
What seems to be the problem, is it the formatting on the json? if it is, is there any way to get around it?
Programming for iOS 7
Any help is much appreciated!
Don't use these many lines use below code for it :
NSMutableURLRequest *request =[[NSMutableURLRequest alloc]initWithURL:[NSURL URLWithString:#"http://appwhittle.com/api/db_all.php"]];
NSData *returnData = [ NSURLConnection sendSynchronousRequest:request returningResponse: nil error: nil ];
NSString *returnString = [[NSString alloc]initWithData:returnData encoding:NSUTF8StringEncoding];
NSError *err = nil;
NSMutableArray *search = [NSJSONSerialization JSONObjectWithData:[returnString dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableContainers error:&err];
NSLog(#"Search %#",search);
-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [search count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *store=#"cell";
UITableViewCell *utvc = [tableView dequeueReusableCellWithIdentifier:store];
if(utvc == nil)
{
utvc = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
}
NSString *str = [[[search valueForKey:#"locations"]objectAtIndex:indexPath.row]valueForKey:#"location"];
NSLog(#"%#", str);
return utvc;
}
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
}
Try to use NSMutableArray for collecting data from connectionDidFinishLoading method.
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 starting NSURLConnection, parsing XML, initialize array from this XML, and show it in the tableView. In connectionDidFinishLoading I'm trying [self.tableView reloadData, but it doesn't work. This is my code:
my .h file:
#interface catalogViewController : UITableViewController //
#property (nonatomic, strong) NSMutableData *receivedData;
#property (nonatomic,retain) NSArray * titleArr;
#property (nonatomic,retain) NSArray * contentArr;
#property (nonatomic,retain) NSArray * ImageURLArr;
#property (nonatomic,retain) NSArray * dateArr;
#property (nonatomic,retain) NSArray * priceArr;
#property (nonatomic,retain) NSDictionary * xmlDictionary;
#property (nonatomic,retain) NSArray * IDArr;
#property (nonatomic) BOOL * didDataLoaded;
#property (strong, nonatomic) IBOutlet UITableView *myTableView;
#end
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 =[[[_xmlDictionary objectForKey:#"result"] objectForKey:#"name"] valueForKey:#"text"];
_IDArr =[[[_xmlDictionary objectForKey:#"result"] objectForKey:#"id"] valueForKey:#"text"];
_priceArr=[[[_xmlDictionary objectForKey:#"result"] objectForKey:#"price"] valueForKey:#"text"];
_ImageURLArr=[[[_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
XML downloading - OK, parsing - OK, initialising arrays - OK. But when I start project I have exception on the line NSLog(#"%#", self.titleArr objectAtIndex:indexPath.row]; - says: "Thread 1: EXC_BAD_ACCESS (code 1)
How can I understand it's means that it's trying initialize array when it's not prepare. My problem is i can't delay tableView methods or what? How can i fix it? I'm trying fix itfor some days...
Your titleArr is deallocated from memory and then you are requesting object of it so it is giving you a crash. So allocate memory to array by this way.
_titleArr = [[NSArray alloc] initWithArray:[[[_xmlDictionary objectForKey:#"result"] objectForKey:#"name"] valueForKey:#"text"]];
Eventhough it's not recommended way but the following can provide a solution to you
self.tableView.delegate = nil;
self.tableView.datasource = nil;
and when safely your array was populated with the xml data set back to
self.tableView.delegate = self;
self.tableView.datasource = self;
For my code, I am following instruction on this link http://www.youtube.com/watch?v=RJZcD3hfs3k and success,
but I want to modify to multiple JSON and failed (if i print log, that its running).
I modify in:
- (void)viewDidLoad
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
This is my modified code(ViewController.m) :
#import "ViewController.h"
#import "DetailViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"News";
//[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
//before
//NSURL *url = [NSURL URLWithString:#"http://zacandcatie.com/YouTube/json.php"];
//after
NSURL *url = [NSURL URLWithString:#"http://service.berisiknews.com/article/byAll/0/3"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
// Do any additional setup after loading the view, typically from a nib.
}
- (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;
//before
//news = [NSJSONSerialization JSONObjectWithData:data options:nil error:nil];
//[mainTableView reloadData];
//ßNSLog(#"array %#", news);
//after
NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData:data options: NSJSONReadingMutableContainers error: nil];
NSArray *news = [jsonArray valueForKeyPath:#"data"];
[mainTableView reloadData];
NSLog(#"array %#", news);
}
- (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)numberINSectionsInTableView: (UITableView *)tableView
{
return 1;
}
- (int)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [news count];
//return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MainCell"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"MainCell"];
}
cell.textLabel.text = [[news objectAtIndex:indexPath.row] objectForKey:#"title"];
//cell.detailTextLabel.text = [[news objectAtIndex:indexPath.row] objectForKey:#"date_string"];
cell.detailTextLabel.text = [[news objectAtIndex:indexPath.row] objectForKey:#"category_name"];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil];
detailViewController.title = [[news objectAtIndex:indexPath.row] objectForKey:#"title"];
detailViewController.newsArticle = [news objectAtIndex:indexPath.row];
[self.navigationController pushViewController:detailViewController animated:YES];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Any help?
Your news array is a local variable as your code.
In connectionDidFinishLoading, please modify as below
NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData:data options: NSJSONReadingMutableContainers error: nil];
news = [jsonArray valueForKeyPath:#"data"];
[mainTableView reloadData];
NSLog(#"array %#", news);
so it will be the right news array which your are accessing in table view.
it works fine for me.
#interface AlbumViewController ()
#end
#implementation AlbumViewController
- (void)viewDidLoad
{
[super viewDidLoad];
//navigation Controller
[self.navigationController setNavigationBarHidden:NO];
self.title=#"Album List";
//json data parsing
NSURL *url = [NSURL URLWithString:#".......your Link......"];
NSURLRequest *urlrequest = [[NSURLRequest alloc]initWithURL:url];
NSData *data = [NSURLConnection sendSynchronousRequest:urlrequest returningResponse:nil error:nil];
dict_data = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
self.ary_data = [dict_data objectForKey:#"album"];
NSLog(#"%#",self.ary_data);
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [ary_data count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#""];
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
NSMutableDictionary *dic= [[ary_data objectAtIndex:indexPath.row] mutableCopy];
AlbumCellController *albumCell = [[AlbumCellController alloc]init];
[cell.contentView addSubview:albumCell.view];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
albumCell.Img_album.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[dic objectForKey:#"cover_photo"]]]];
});
albumCell.lbl_name.text = [dic objectForKey:#"title"];
albumCell.lbl_releasedate.text = [dic objectForKey:#"release_date"];
NSString *SongNo=[dic objectForKey:#"no_of_songs"];
NSLog(#"%#",SongNo);
//albumCell.lbl_songno.text=SongNo;
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSMutableDictionary *dic= [[ary_data objectAtIndex:indexPath.row] mutableCopy];
SongsViewController *songList = [[SongsViewController alloc]init];
songList.imgURL = [dic objectForKey:#"cover_photo"];
songList.Album_id = [dic objectForKey:#"album_id"];
[self.navigationController pushViewController:songList animated:YES];
}