I am trying to populate a UITableView in my viewcontroller (it is a delegate of UITableView)
The code below is something I've found online. I've made some changes so that I didn't need a UITableViewController in order to use it. However since I changed it, I am unable to figure out how to get the text to print in the cells. Before changing the code to allow my ViewcController subclass to be a delegate of UITableView. Could anyone point me in the right direction?
I have checked and the XML is parsing correctly. When the code reaches the if (marrXMLData.count != 0) in the startParsing method, marrXMLData is greater than 0 (8 being specific, the correct and total number of items in my XML)
code is from: http://www.theappguruz.com/blog/xmlparsing-with-nsxmlparser-tutorial
.m is below
DisplayTableViewController
#synthesize marrXMLData;
#synthesize mstrXMLString;
#synthesize mdictXMLPart;
- (void)viewDidLoad{
[super viewDidLoad];
[self startParsing];
}
- (void)startParsing{
NSData *fileData = [NSData dataWithContentsOfFile:[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"file.xml"]];
NSXMLParser *xmlparser = [[NSXMLParser alloc] initWithData:fileData];
[xmlparser setDelegate:self];
[xmlparser parse];
if (marrXMLData.count != 0) {
[self.myUITableView reloadData];
}
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict;{
if([elementName isEqualToString:#"Content"])
marrXMLData = [[NSMutableArray alloc] init];
if([elementName isEqualToString:#"item"])
mdictXMLPart = [[NSMutableDictionary alloc] init];
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string;{
if(!mstrXMLString)
mstrXMLString = [[NSMutableString alloc] initWithString:string];
else
[mstrXMLString appendString:string];
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName;{
if([elementName isEqualToString:#"title"] || [elementName isEqualToString:#"url"]){
[mdictXMLPart setObject:mstrXMLString forKey:elementName];
}
if([elementName isEqualToString:#"item"])
[marrXMLData addObject:mdictXMLPart];
mstrXMLString = nil;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection: (NSInteger)section{
return [marrXMLData count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
cell.textLabel.text = [[[marrXMLData objectAtIndex:indexPath.row] valueForKey:#"title"] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
cell.detailTextLabel.text = [[[marrXMLData objectAtIndex:indexPath.row] valueForKey:#"url"] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
return cell;
}
#end
EDIT:
After playing with it some more this method is not being called
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
In the example code it is being called, but I'm not sure where. (Sorry, I am very new to iOS)
It sounds like your table view's delegate and/or dataSource links are not connected. If you set up the table view scene in IB (Interface Builder) then you just control-drag from the table view onto the view controller.
Related
I have xml file which I have to parse it. I'm following a youtube tutorials for it. I'm showing the parsed data from tags in a table view controller, But when i run the app no data is shown there, the table view controller is just empty. My code for parsing the file is this,
#import "QuestionParser.h"
#import "Question.h"
#interface QuestionParser()
#property NSXMLParser *parser;
#property NSString *element;
#property NSString *currentxref;
#property NSString *currenttext;
#property NSString *currentprompt;
#property NSString *currentexplanation;
#property NSString *currenttext1;
-(id)initWithArray:(NSMutableArray *)questionArray{
self = [super init];
if (self) {
self.questionArray = questionArray;
}
return self;
}
-(void)parseFile{
NSURL *url= [[NSBundle mainBundle]URLForResource:#"test" withExtension:#"xml"];
self.parser = [[NSXMLParser alloc]initWithContentsOfURL:url];
self.parser.delegate=self;
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
attributes:(NSDictionary<NSString *,NSString *> *)attributeDict{
self.element = elementName;
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
if ([self.element isEqualToString:#"xref"]) {
self.currentxref = string;
}
else if ([self.element isEqualToString:#"text"]){
self.currenttext = string;
}
else if ([self.element isEqualToString:#"prompt"]){
self.currentprompt = string;
}
else if ([self.element isEqualToString:#"explanation"]){
self.currentexplanation = string;
}
else if ([self.element isEqualToString:#"text"]){
self.currenttext1 = string;
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
if ([elementName isEqualToString:#"question"]) {
Question *ques= [[Question alloc]initWithName:_currentxref text:_currenttext prompt:_currentprompt explanation:_currentexplanation text1:_currenttext1];
[self.questionArray addObject:ques];
}
self.element = nil;
}
This is how I'm loading data in datasource,
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.questionArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
Question *ques=self.questionArray[indexPath.row];
cell.textLabel.text=ques.xref;
cell.detailTextLabel.text = [NSString stringWithFormat:#"%#",ques.prompt];
return cell;
}
My xml file is this,
This method will execute after complete XML parsing. In this method reload the table view data.
-(void)parserDidEndDocument:(NSXMLParser *)parser{
// When the parsing has been finished then simply reload the table view.
[self.tableView reloadData];
}
If you want anything please follow this tutorial: https://www.appcoda.com/parse-xml-and-json-web-service/
I am trying to implement an rss reader into a table inside a container. I have the code of the parser in an other project and in the specific project it works fine without any error. I copied every file, 4 files exactly as they are in the other project and i copied also the view controllers into my storyboard so they are exactly the same. But when i run the code i get an error!
here is a pic with my error.
I don't know why is this happening. In the other project which has only two view controllers with the table view and the web view it works fine. But when i try to copy every file as it is into my other project I get this error.
This is my .m file
#import "APPMasterViewController.h"
#import "APPDetailViewController.h"
#interface APPMasterViewController () {
NSXMLParser *parser;
NSMutableArray *feeds;
NSMutableDictionary *item;
NSMutableString *title;
NSMutableString *link;
NSString *element;
}
#end
#implementation APPMasterViewController
(void)awakeFromNib {
[super awakeFromNib];
}
- (void)viewDidLoad {
[super viewDidLoad];
feeds = [[NSMutableArray alloc] init];
NSURL *url = [NSURL URLWithString:#"http://radioevros.gr/feed/"];
parser = [[NSXMLParser alloc] initWithContentsOfURL:url];
[parser setDelegate:self];
[parser setShouldResolveExternalEntities:NO];
[parser parse];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
#pragma mark - Table View
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return feeds.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
cell.textLabel.text = [[feeds objectAtIndex:indexPath.row] objectForKey: #"title"];
return cell;
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI: (NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
element = elementName;
if ([element isEqualToString:#"item"]) {
item = [[NSMutableDictionary alloc] init];
title = [[NSMutableString alloc] init];
link = [[NSMutableString alloc] init];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
if ([elementName isEqualToString:#"item"]) {
[item setObject:title forKey:#"title"];
[item setObject:link forKey:#"link"];
[feeds addObject:[item copy]];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if ([element isEqualToString:#"title"]) {
[title appendString:string];
} else if ([element isEqualToString:#"link"]) {
[link appendString:string];
}
}
- (void)parserDidEndDocument:(NSXMLParser *)parser {
[self.tableView reloadData];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"showDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
NSString *string = [feeds[indexPath.row] objectForKey: #"link"];
[[segue destinationViewController] setUrl:string];
}
}
-(void) viewDidUnload{
[element release];
element = nil;
[super viewDidUnload];
}
- (void)dealloc {
[element release];
[super dealloc];
}
#end
I can't say for certain since I haven't tried running your code, but you may want to try to store element using element = [elementName copy]; instead and see if that gets rid of the exception.
My guess is that elementName gets deallocated after you exit the method since it is only a local parameter variable.
As a side note, it appears that you are doing manual memory management. I highly suggest that you convert your project to use ARC since it not only streamlines memory management, it is also what Apple has been recommending to use for quite a while now.
I tried load an array from web service and display on tableview, But I have a problem.
I dont want display duplicate fields on tableview.
I want display only one field on table.
Now I have :
1234
1235
1234
6544
2234
6544
e.g 1234 and 6544 have duplicate
Load Array Code :
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes: (NSDictionary *)attributeDict
{
if ( [elementName isEqualToString:#"BranchID"] )
{
teveRetorno = YES;
}
else if ( [elementName isEqualToString:#"GetBranchResult"] )
{
myArray = [[NSMutableArray alloc] init];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if (teveRetorno)
{
[myArray addObject:string];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if ( [elementName isEqualToString:#"BranchID"] )
{
[[self tableView]reloadData];
}
teveRetorno = NO;
}
Table Code:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 5;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.myArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text =[myArray objectAtIndex:indexPath.row];
cell.textLabel.adjustsFontSizeToFitWidth = YES;
[cell setAccessoryType: UITableViewCellAccessoryDisclosureIndicator];
return cell;
}
Remove the duplicates from the array you're using to populate the table. This can be done with:
NSOrderedSet *distinctItems = [NSOrderedSet orderedSetWithArray:self.myArray];
self.myArray = [distinctItems array];
Do this after you populate myArray from your data load and before you reload the table view.
This has not to do anything with tableView.
You might want to use something like this
if(![array containsObject:Value])
{
//add object to array.
}
if condition is true then only add value otherwise don't add it.
Deal with your datasource array.Remove the duplicate entries.Then Load data via reloadData
I tried load an array from web service and display on table view.This my tableview.But there is a mistake.Branchnames are
MEHMET FUDAYLÖZCAN,
SELAHATTİN KOÇAK,
Mehmet Süner Eken Petrol
Hasan Katkıcı Petrol
etc
etc
but table view show me like that
How I fix this ?
Th
Array Codes :
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes: (NSDictionary *)attributeDict
{
if ( [elementName isEqualToString:#"Branchname"] )
{
teveRetorno = YES;
}
else if ( [elementName isEqualToString:#"GetBranchNameResult"] )
{
myArray = [[NSMutableArray alloc] init];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
if (teveRetorno) {
//[retornoSOAP appendString:string];
[myArray addObject:string];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
if ( [elementName isEqualToString:#"Branchname"] ) {
NSLog(#"My Array %#",myArray);
[[self tableView]reloadData];
//retornoSOAP = nil;
teveRetorno = NO;
}
}
Table Codes
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
#warning Incomplete method implementation.
// Return the number of rows in the section.
return [self.myArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text =[myArray objectAtIndex:indexPath.row];
return cell;
}
There is nothing wrong with your table view or output. Your XMLParser is getting confused by certain characters (Ö) and calling didStartElement too early. Check out this - NSXMLParser divides strings containing foreign(unicode) characters
If your asking about the reason the text is getting cut off, set adjustsFontSizeToFitWidth for the textLabel of the cell. If that dosent fix it, then manually lower the font of the textLabel.
The goal of my application is to parse some XML, display one element of the xml in a tableview and then have the user click on the cell, and it pushes to a new table view where the rest of the data for that element is displayed. The first table view that displays only the list works fine, but for some reason I can't get the push to a new view controller to work. Below is the code I am using. The first view controller displays in a table view; currentCallType. I wan the user to be be able to click on that table cell, then push to a new table view where it displays the units, station and location. Any help would be AWESOME! thanks.
View controller for first tableview:
#import "ThirdViewController.h"
#import "UnitsXMLParser.h"
#import "DetailViewController"
#implementation ThirdViewController
#synthesize unitsTableView;
#synthesize currentCallType, station, location, units;
XMLParser1 *xmlParser;
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark -
#pragma mark Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[xmlParser units] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
Units *currentCall = [[xmlParser units] objectAtIndex:indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
// Set up the cell...
cell.textLabel.text = [currentCall currentCallType];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 55;
}
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
DetailViewController *detail = [self.storyboard instantiateViewControllerWithIdentifier:#"detail"];
[self.navigationController pushViewController:detail animated:YES];
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
xmlParser = [[XMLParser1 alloc] loadXMLByURL:#"http://localhost:8888/units.xml"];
}
XML Parser:
#import <Foundation/Foundation.h>
#import "UnitsXMLParser.h"
#implementation XMLParser1
#synthesize units = _units;
NSMutableString *currentNodeContent;
NSXMLParser *parser;
Units *currentCall;
bool isStatus;
-(id) loadXMLByURL:(NSString *)urlString
{
_units = [[NSMutableArray alloc] init];
NSURL *url = [NSURL URLWithString:urlString];
NSData *data = [[NSData alloc] initWithContentsOfURL:url];
parser = [[NSXMLParser alloc] initWithData:data];
parser.delegate = self;
[parser parse];
return self;
}
- (void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
currentNodeContent = (NSMutableString *) [string stringByReplacingOccurrencesOfString:#"~" withString:#""];
}
- (void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementname namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
if ([elementname isEqualToString:#"station"])
{
currentCall = [Units alloc];
isStatus = YES;
}
}
- (void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementname namespaceURI: (NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if (isStatus)
{
if ([elementname isEqualToString:#"units"])
{
currentCall.units = currentNodeContent;
}
if ([elementname isEqualToString:#"name"])
{
currentCall.currentCallType = currentNodeContent;
}
if ([elementname isEqualToString:#"stationid"])
{
currentCall.station = currentNodeContent;
}
if ([elementname isEqualToString:#"address"])
{
currentCall.location = currentNodeContent;
}
}
if ([elementname isEqualToString:#"station"])
{
[self.units addObject:currentCall];
currentCall = nil;
currentNodeContent = nil;
}
}
#end
A longshot; but do you have your project configured to use a UINavigationController ? Your view controllers will not be contained in / managed by a UINavigationController unless you start with the correct project template or manually add the UINavigationController . If the view controller containing your posted code is not backed by a navigation controller, [self.navigationController pushViewController:detail animated:YES] will do nothing.
Also, make sure that you have hooked up your UITableViewDelegate in addition to your UITableViewDataSource , so that your code will catch the row selection.
I only ask because you do not explicitly state that you have set up your project to use a UINavigationController or confirm that you have hooked up both the delegate and datasource in Interface Builder.