i'm having some troubles trying to parse an XML file and display the results grouped by an object property on a UITableView.
This is the XML file, I can change the structure if it's necessary:
<Anuncios>
<Anuncio id="1">
<localeName>name1</localeName>
<address>address1</address>
<type>A</type>
</Anuncio>
<Anuncio id="2">
<localeName>name2</localeName>
<address>address2</address>
<type>B</type>
</Anuncio>
<Anuncio id="3">
<localeName>name3</localeName>
<address>address3</address>
<type>A</type>
</Anuncio>
</Anuncios>
At this moment I have a NSMutableArray called servs containing objects (Anuncio).
This is the structure:
#interface Anuncio : NSObject
NSInteger iden;
NSString *localeName;
NSString *address;
NSString *type;
So, I would like to sort the UITableView by anuncio.type with the correct titleForHeaderInSection.
I downloaded the TableViewSuite from the Apple documentation, and the second example, SimpleSectionedTableView seems to do what I want, but instead of getting the data from an XML file, it gets the data calling [NSTimeZone knownTimeZoneNames], so the structure is quite different, I tried to adapt the sample code to my project, but i'm starting to realize that seems to be not the best way to do it. So I'm a bit stuck.
I was thinking on having arrays inside the main array containing the objects editing the XML, like that:
servs: {
arrayA : { anuncio1, anuncio3 }
arrayB : { anuncio2 }
}
but then I don't know how to complete the tableView methods.
Here it is the XMLParse code:
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict {
if([elementName isEqualToString:#"Anuncios"]) {
//Initialize the array.
appDelegate.servs = [[NSMutableArray alloc] init];
}
else if([elementName isEqualToString:#"Anuncio"]) {
//Initialize the anuncio.
serv = [[Anuncio alloc] init];
//Extract the attribute here.
serv.iden = [[attributeDict objectForKey:#"id"] integerValue];
NSLog(#"Reading id value: %i", serv.iden);
}
NSLog(#"Processing Element: %#", elementName);
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if(!currentElementValue)
currentElementValue = [[NSMutableString alloc] initWithString:string];
else
[currentElementValue appendString:string];
NSLog(#"Processing Value: %#", currentElementValue);
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
if([elementName isEqualToString:#"Anuncios"])
return;
if([elementName isEqualToString:#"Anuncio"]) {
[appDelegate.servs addObject:serv];
[serv release];
serv = nil;
}
else
[serv setValue:currentElementValue forKey:elementName];
[currentElementValue release];
currentElementValue = nil;
}
Part of my current UITableViewController:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [appDelegate.servs count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 1;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
anuncios = (NSMutableArray *)[appDelegate.servs sortedArrayUsingSelector:#selector(compare:)];
Anuncio *anuncio = [anuncios objectAtIndex:section];
return [anuncio type];
}
- (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] autorelease];
}
anuncios = (NSMutableArray *)[appDelegate.servs sortedArrayUsingSelector:#selector(compare:)];
Anuncio *anuncio = [anuncios objectAtIndex:indexPath.section];
cell.textLabel.text = anuncio.localeName;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
At the moment I get:
A
--------
name1
--------
A
--------
name3
--------
B
--------
name2
and I would like to get:
A
--------
name1
name3
--------
B
--------
name2
I don't know if the model that I'm proposing is the right one or i'm missing something. I thought it was something very common but I didn't find anything about this.
Thanks for helping
In your Anuncio class, add a compare: method like this:
- (NSComparisonResult) compare:(Anuncio *)otherObject {
return [self.type compare:otherObject.type];
}
Then sort your NSMutableArray with this:
anuncios = (NSMutableArray *)[anuncios sortedArrayUsingSelector:#selector(compare:)];
Related
I want to add a UISearchBarto the following code below, that I am using in Xcode 4.6.
Can someone please help me?
//
#import "SocialMasterViewController.h"
#import "SocialDetailViewController.h"
#interface SocialMasterViewController () {
NSXMLParser *parser;
NSMutableArray *feeds;
NSMutableDictionary *item;
NSMutableString *title;
NSMutableString *link;
NSString *element;
NSArray *filteredStrings;
}
#end
#implementation SocialMasterViewController
-(void)gotosharing {
UIStoryboard *sharingStoryboard = [UIStoryboard storyboardWithName:#"Sharing" bundle:nil];
UIViewController *initialSharingVC = [sharingStoryboard instantiateInitialViewController];
initialSharingVC.modalTransitionStyle = UIModalTransitionStylePartialCurl;
[self presentViewController:initialSharingVC animated:YES completion:nil];
}
- (void)awakeFromNib
{
[super awakeFromNib];
}
- (void)viewDidLoad {
[super viewDidLoad];
feeds = [[NSMutableArray alloc] init];
NSURL *url = [NSURL URLWithString:#"http://www.rssmix.com/u/3735817/rss.xml"
];
parser = [[NSXMLParser alloc] initWithContentsOfURL:url];
[parser setDelegate:self];
[parser setShouldResolveExternalEntities:NO];
[parser parse];
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:#selector(refresh:) forControlEvents:UIControlEventValueChanged];
[self.tableView addSubview:refreshControl];
}
- (void)refresh:(UIRefreshControl *)refreshControl {
[refreshControl endRefreshing];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#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)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
[self filterURLsWithSearchBar:searchText];
[self.tableView reloadData];
}
- (void)filterURLsWithSearchBar:(NSString *)searchText
{
//[filteredStrings removeAllObjects];
for (NSString *rssUrl in feeds)
{
NSComparisonResult result = [rssUrl compare:searchText
options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch)
range:[rssUrl rangeOfString:searchText options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch)]];
if (result == NSOrderedSame) {
[self->feeds addObject:filteredStrings];
}
}
}
#end
Basically, I am want to filter the results of what is brought in by the NSXMLParser into search terms as they are typed into a search bar.
Any help is much appreciated from you guys/gals.
Do this
Store the value get from parser into an array. responseArray
Use another array to store the value to show in table
datasourceArray
After webvservice recieve successful response datasourceArray=responseArray then reload table with [tableView reloadData]
When search starts,search from responseArray load the result into DatasourceArray then call reloadData again
you can use textFeildDidBegunEditingdelegate method of uitextFeild
then this code will help you filter
NSMutableArray *array1=(NSMutableArray*)[txtEditFavoriteColor.text componentsSeparatedByString:#" "];//words from textFeild
for (NSString *str in array1)
{
NSString *tempStr = [str stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if([tempStr length])
{
[arryOfWordsToBeSearched addObject:tempStr];
}
}
NSMutableArray *subpredicates = [NSMutableArray array];
for(NSString *term in arryOfWordsToBeSearched) {
NSPredicate *p = [NSPredicate predicateWithFormat:#"name contains[cd] %#",term];
[subpredicates addObject:p];
}
NSPredicate *filter = [NSCompoundPredicate andPredicateWithSubpredicates:subpredicates];
//***************************************************************predicate made above******
result = [[NSMutableArray alloc]initWithArray:[arryOfDummyData filteredArrayUsingPredicate: filter]];//search on data array using predicate
Create table view controller subclass with nibfile. Add search bar to nibfile at top of table view. Then search result view controller will be added automatically.
most of the property of searchResultViewController like delegate, searchBar ,searchDisplayDatasource and delegate are automatically set. and also for search bar delegate is set as file owner.
Now implement table view conform to this protocol . .
Implement the following delegate method .
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
// create the array of ur search result object
}
now implementing tableViewDataSource and delegate check which table is calling method
as follows
if (tableView == self.searchDisplayController.searchResultsTableView)
{
// searchResultsTableView
}
else
{
// main table view
}
implement the corresponding code.
Its my first experience with xmls so please don't be harsh on me if my question is low quality. I am working on app where I retrieve all data using xml files from server.
Before posting question here I read some Tutorials about xml file parsing. But when I start to implement it in my app, then I am totally confused at the point when I am trying to parse the second Xml file and so on.
Now I want to explain my app flow using some screenshot so that it become easy for everyone that what I want.
First view
Second view
Third view
Now when I click in any row in first view it goes to second view and show all related data in second view and when I click any item in Second view it goes to the third view and show detail information about that particular item.
After explanation of app flow, now I show my code what I tried so far. Following a tutorial I just simply drag classes (XMLParser, Book) to my app for testing purpose.
Code:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSURL *url = [[NSURL alloc] initWithString:#"Firstviewxmlurl"];
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
XMLParser *parser = [[XMLParser alloc] initXMLParser];
[xmlParser setDelegate:parser];
BOOL success = [xmlParser parse];
if(success)
NSLog(#"No Errors");
else
NSLog(#"Error Error Error!!!");
}
Now my XMLParser.m code is
- (XMLParser *) initXMLParser {
[super init];
appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
return self;
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict {
if([elementName isEqualToString:#"Collections"]) {
//Initialize the array.
appDelegate.books = [[NSMutableArray alloc] init];
}
else if([elementName isEqualToString:#"Collection"]) {
//Initialize the book.
aBook = [[Book alloc] init];
//Extract the attribute here.
aBook.bookID = [[attributeDict objectForKey:#"id"] integerValue];
NSLog(#"Reading id value :%i", aBook.bookID);
}
NSLog(#"Processing Element: %#", elementName);
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if(!currentElementValue)
currentElementValue = [[NSMutableString alloc] initWithString:string];
else
[currentElementValue appendString:string];
NSLog(#"Processing Value: %#", currentElementValue);
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
if([elementName isEqualToString:#"Collections"])
return;
if([elementName isEqualToString:#"Collection"]) {
[appDelegate.books addObject:aBook];
[aBook release];
aBook = nil;
}
else
[aBook setValue:currentElementValue forKey:elementName];
[currentElementValue release];
currentElementValue = nil;
}
Finaly my First view Class code is
#pragma mark Table Methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
//return [tblViewData count];
return [appDelegate.books count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"SimpleTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell=[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
cell.selectionStyle=UITableViewCellSelectionStyleGray;
cell.accessoryType=UITableViewCellAccessoryDisclosureIndicator;
}
//cell.textLabel.text=[[tblViewData objectAtIndex:indexPath.row]
// stringByReplacingOccurrencesOfString:#"*" withString:#""];
Book *aBook = [appDelegate.books objectAtIndex:indexPath.row];
cell.textLabel.text = aBook.title;
if([deviceType isEqualToString:#"ipad"])
{
[cell.textLabel setFont:[UIFont fontWithName:#"Helvetica-Bold" size:20]];
}
//cell.textLabel.font=[UIFont fontWithName:#"Walkway_SemiBold" size:16];
return cell;
}
After implementation of all the above Code i got the result in form of this Now at this point i confuse how can i pass my Second view xml file url and then third view url.my xml files are in this format
First xml file
<?xml version="1.0" encoding="UTF-8"?>
<Collections> <Collection id="5"><title>Allegroo</title> </Collection>
Second xml file
<?xml version="1.0" encoding="UTF-8"?>
<Collection id="5"><colletciontitle>Allegroo</colletciontitle> <weaveimage>"imageurl" </weaveimage><Rug id="48"><Rugthumb>"firstimageurl"</Rugthumb><RugSku>AL-637</RugSku></Rug><Rug id="51"><Rugthumb>"Secondimageurl"</Rugthumb><RugSku>AL-641</RugSku></Rug>
Third xml file
<?xml version="1.0" encoding="UTF-8"?>
<Rug id="47"><Rugmainimage>"imageurl"</Rugmainimage> <Rugtitle>AL-636 Aged Indigo / Vintage Beige</Rugtitle> <Rugdiscription>Hand Knotted
Distressed Wool Pile / Cotton Foundation </Rugdiscription><Availablesizes><Size>10x14</Size><Size>12x15</Size><Size>2x3</Size><Size>3x5</Size><Size>4x6</Size><Size>6x9</Size><Size>8x10</Size><Size>9x12</Size><Runner>2'6"x10'</Runner><Runner>2'6"x12'</Runner><Runner>2'6"x8'</Runner></Availablesizes></Rug>
Any help in the form of link or sample code releated to my issue and suggestion will be highly appriated.Thanks
Hmm, So Defining long story short, you want to parse multiple urls in sequence ?
So here is the answer,
Use a variable / identifier in appDelegate that tells you which xml is being parsed.
Use your xml parser as delegate class object
Use delegate method to swich to next xml parsing
- (void)parserDidEndDocument:(NSXMLParser *)parser {
// Change URL accordingly
NSURL *url = [[NSURL alloc] initWithString:#"Firstviewxmlurl"];
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
XMLParser *parser = [[XMLParser alloc] initXMLParser];
[xmlParser setDelegate:parser];
BOOL success = [xmlParser parse];
}
I have added some of the code to make you understand. Try to implement according to your condition. Below code is just to refer as i havn't made all the changes u need to understand first and then implement accordingly
//int i = 0; // in AppDelegate
Code:
//Or ViewDidLoad Method
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
int = 1; //For First View
NSURL *url = [[NSURL alloc] initWithString:#"Firstviewxmlurl"];
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
XMLParser *parser = [[XMLParser alloc] initXMLParser];
[xmlParser setDelegate:parser];
BOOL success = [xmlParser parse];
if(success)
NSLog(#"No Errors");
else
NSLog(#"Error Error Error!!!");
}
XMLParser.m
- (XMLParser *) initXMLParser
{
[super init];
appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
return self;
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict {
if([elementName isEqualToString:#"Collections"])
{
//Initialize the array.
if (int == 1)
appDelegate.books = [[NSMutableArray alloc] init];
else if (int == 2)
appDelegate.secondArray = [[NSMutableArray alloc] init];
else if (int == 3)
appDelegate.thirdArray = [[NSMutableArray alloc] init];
}
else if([elementName isEqualToString:#"Collection"])
{
if (i == 1)
{
//Initialize the book.
aBook = [[Book alloc] init];
//Extract the attribute here.
aBook.bookID = [[attributeDict objectForKey:#"id"] integerValue];
NSLog(#"Reading id value :%i", aBook.bookID);
}
else if (i == 2)
{
//Second Xml
}
else if (i == 3)
{
//Third Xml
}
}
NSLog(#"Processing Element: %#", elementName);
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
//Check condition
if(!currentElementValue)
currentElementValue = [[NSMutableString alloc] initWithString:string];
else
[currentElementValue appendString:string];
NSLog(#"Processing Value: %#", currentElementValue);
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
//Check COndition
if([elementName isEqualToString:#"Collections"])
return;
if([elementName isEqualToString:#"Collection"]) {
[appDelegate.books addObject:aBook];
[aBook release];
aBook = nil;
}
else
[aBook setValue:currentElementValue forKey:elementName];
[currentElementValue release];
currentElementValue = nil;
}
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
- (void)viewDidLoad
{
NSURL *url=[[NSURL alloc]initWithString:#"http://avweatherforecasts.com/services/iphoneservice.php"];
DaTa=[[NSData alloc]initWithContentsOfURL:url];
NSLog(#"data----%#",DaTa);
Xmlpaeser=[[NSXMLParser alloc]initWithData:DaTa];
Xmlpaeser.delegate=self;
[Xmlpaeser parse];
[Xmlpaeser release];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)parserDidStartDocument:(NSXMLParser *)parser{
array=[[NSMutableArray alloc]init];
strcontent=nil;
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
if ([elementName isEqualToString:#"start"])
{
Dict=[[NSMutableDictionary alloc]init];
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
strcontent=[NSString stringWithFormat:#"%#",string];
NSLog(#"Strcontent----%#",strcontent);
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
if ([elementName isEqualToString:#"city"]){
[Dict setObject:strcontent forKey:elementName];
}
if ([elementName isEqualToString:#"min"]){
[Dict setObject:strcontent forKey:elementName];
}
if ([elementName isEqualToString:#"max"]){
[Dict setObject:strcontent forKey:elementName];
}
if ( [elementName isEqualToString:#"forecast"]
) {
[Dict setObject:strcontent forKey:elementName];
NSLog(#"dict--%#",[Dict description]);
}
else if([elementName isEqualToString:#"start"]){
[array addObject:Dict];
[Dict release];
}
}
- (void)parserDidEndDocument:(NSXMLParser *)parser{
NSLog(#"array--%#",[array description]);
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [array count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier=#"cell";
custome_cell *Cell=(custome_cell *)[tableView dequeueReusableCellWithIdentifier:identifier];
if (Cell==nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"custome_cell" owner:self options:nil];
Cell = [nib objectAtIndex:indexPath.row];
}
Cell.city.text=[[array objectAtIndex:indexPath.row] objectForKey:#"city"];
Cell.min.text=[[array objectAtIndex:indexPath.row] objectForKey:#"min"];
Cell.max.text=[[array objectAtIndex:indexPath.row] objectForKey:#"max"];
Cell.forecast.text =[[array objectAtIndex:indexPath.row] objectForKey:#"forecast"];
return Cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 80;
}
Try this...May be it will help you...
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [CommentsGetArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] ;
//[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
commentsTextView = [[UITextView alloc]initWithFrame:CGRectMake(90, 4, 190, 50)];
commentsTextView.delegate = self;
commentsTextView.tag = 101;
commentsTextView.textAlignment = UITextAlignmentLeft;
[commentsTextView setScrollEnabled:YES];
commentsTextView.backgroundColor =[UIColor clearColor];
commentsTextView.font = [UIFont fontWithName:#"Arial" size:12.0];
commentsTextView.textColor =[UIColor blackColor];
commentsTextView.editable = NO;
[cell addSubview:commentsTextView];
}
commentsTextView = (UITextView *)[cell viewWithTag:101];
commentsTextView.text = [[CommentsGetArray objectAtIndex:indexPath.row]objectForKey:#"comment"];
return cell;
}
- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 70;
}
you can use as a label instead of uitextView and you can create more text views or label to show your data but remember change their frames.
I'm a newbie to Objective-C & iPhone development, hence please bear with me.
I'm working on an app which loads with UITableView and upon selecting one particular cell called "Address Book" it should load with another UITableView containing all the addresses retrieved from a web request. Using NSXMLParser's delegate methods I'm storing those addresses into a NSMutableArray defined in the loaded view's header file. But the problem occurs when those addresses are being displayed onto the UITableView cells (yes, I have got the count for the number of cells). Can anybody please help me with this problem? I'm stuck on this for days now !!! Following is my code:
- (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] autorelease];
}
AddressEntry *entry = (AddressEntry *)[self.addresses objectAtIndex:indexPath.row];
#try
{
NSLog(#"%#", entry.firstName);
}
#catch (NSException * e)
{
#try
{
NSLog(#"%#", entry.lastName);
}
#catch (NSException * e)
{
NSLog(#"%#", entry.lastName);
}
}
[entry release];
return cell;
}
- (void)parserDidStartDocument:(NSXMLParser *)parser
{
self.currentElement = nil;
self.f_Name = nil;
self.l_Name = nil;
self.phone = nil;
self.email = nil;
count = 0;
self.addresses = [[NSMutableArray alloc] init];
}
- (void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
attributes:(NSDictionary *)attributeDict
{
if([elementName isEqualToString:#"Entries"])
{
count = [[attributeDict valueForKey:#"total"] intValue];
}
else if([elementName isEqualToString:#"FirstName"])
{
[self.f_Name release];
self.f_Name = [[NSString alloc] init];
}
else if([elementName isEqualToString:#"LastName"])
{
[self.l_Name release];
self.l_Name = [[NSString alloc] init];
}
else if([elementName isEqualToString:#"PhoneNumber"])
{
[self.phone release];
self.phone = [[NSString alloc] init];
}
else if([elementName isEqualToString:#"EmailAddress"])
{
[self.email release];
self.email = [[NSString alloc] init];
}
else if([elementName isEqualToString:#"Record"])
{
[self.addrEntry release];
self.addrEntry = [[[AddressEntry alloc] init] retain];
}
[self.currentElement release];
self.currentElement = nil;
self.currentElement = [elementName copy];
}
- (void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
{
//
if([elementName isEqualToString:#"FirstName"])
self.addrEntry.firstName = self.f_Name;
else if ([elementName isEqualToString:#"LastName"])
self.addrEntry.lastName = self.l_Name;
else if([elementName isEqualToString:#"PhoneNumber"])
self.addrEntry.mobile = self.phone;
else if([elementName isEqualToString:#"EmailAddress"])
self.addrEntry.emailAddress = self.email;
else if([elementName isEqualToString:#"Record"])
{
[self.addresses addObject:self.addrEntry];
[self.addrEntry release];
self.addrEntry = nil;
/*AddressEntry *e = (AddressEntry *)[self.addresses lastObject];
NSLog(#"%# %# %# %#", e.firstName, e.lastName, e.mobile, e.emailAddress);
[e release];*/
}
}
- (void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if([currentElement isEqualToString:#"FirstName"])
self.f_Name = string;
else if([currentElement isEqualToString:#"LastName"])
self.l_Name = string;
else if([currentElement isEqualToString:#"PhoneNumber"])
self.phone = string;
else if([currentElement isEqualToString:#"EmailAddress"])
{
self.email = string;
}
}
The most likely reason for the app crashing is this line in cellForRowAtIndexPath:
[entry release];
You did not alloc/init the variable entry there so don't call release on it. Remove that line.
In that method, entry is only holding a reference to an already-allocated object in the address array. It doesn't "own" the object so it shouldn't release it.
This page in the Apple docs shows a nice flow diagram and some simple rules for memory management that might help in understanding this better.
As a separate issue unrelated to the crashing, the use of #try/#catch in your example seems unnecessary. See this answer for an explanation.
Finally, also unrelated to the crashing, in foundCharacters, you should really be appending the string parameter to your data instead of just assigning because it's possible for that method to be called multiple times within the same value. See Handling XML Elements and Attributes for an example.
How could I display arrayData in table view cell?
I want to set the table view cell's label text to the 'ename' from the data parsed.
Please help me out.
Thanks in Advance.
- (void)viewDidLoad {
NSString *url = [NSString stringWithFormat:#"http://mmabigshow.com/app/get_result_from_query.php?q=select * from event"];
NSString *escapedUrl = [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[self performSelector:#selector(startParsing:) withObject:escapedUrl afterDelay:1.0];
NSLog(#"View Did Load End");*/
[super viewDidLoad];
}
- (void) startParsing: (NSString *) query{
NSLog(#"Start Of Parsing");
NSURL *xmlURL = [[NSURL alloc] initWithString:query];
NSData *myData = [NSData dataWithContentsOfURL:xmlURL];
NSString *myStr = [[NSString alloc] initWithData:myData encoding:NSWindowsCP1252StringEncoding];
myStr = [myStr stringByReplacingOccurrencesOfString:#"encoding=\"windows-1252\"" withString:#""];
NSData* aData = [myStr dataUsingEncoding:NSUTF8StringEncoding];
rssParser = [[NSXMLParser alloc] initWithData:aData];
[rssParser setDelegate:self];
[rssParser setShouldProcessNamespaces:NO];
[rssParser setShouldReportNamespacePrefixes:NO];
[rssParser setShouldResolveExternalEntities:NO];
[rssParser parse];
NSLog(#"End of Parsing");
}
#pragma mark xml parser
#pragma mark -
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
currentElement = [elementName copy];
if ([elementName isEqualToString:#"table"]){
item = [[NSMutableDictionary alloc] init];
currentEid = [[NSMutableString alloc] init];
currentEname = [[NSMutableString alloc] init];
currentEurl = [[NSMutableString alloc] init];
dataArray = [[NSMutableArray alloc] init];
}
//NSLog(#"didStartElement");
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
if ([elementName isEqualToString:#"table"]) {
// save values to an item, then store that item into the array...
[item setObject:currentEname forKey:#"ename"];
//NSLog(#"%#",item);
[dataArray addObject:[[item copy] autorelease]];
//NSLog(#"%#",dataArray);
}
[currentEid release];
[currentEname release];
[currentEurl release];
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
if ([currentElement isEqualToString:#"eid"]) {
[currentEid appendString:string];
} else if ([currentElement isEqualToString:#"ename"]) {
[currentEname appendString:string];
//NSLog(#"%#",currentEname);
} else if ([currentElement isEqualToString:#"eurl"]) {
[currentEurl appendString:string];
}
// NSLog(#"foundCharacters");
}
#pragma mark -
#pragma mark Table Data Source Methods
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section {
NSLog(#"numberOfRowsInSection");
return [self.dataArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"cellForRowAtIndexPath");
static NSString *CustomCellIdentifier = #"CustomCellIdentifier ";
TableDetailsCell *cell = (TableDetailsCell *)[tableView dequeueReusableCellWithIdentifier: CustomCellIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"TableDetailsCell" owner:self options:nil];
for (id oneObject in nib)
if ([oneObject isKindOfClass:[TableDetailsCell class]])
cell = (TableDetailsCell *)oneObject;
}
NSUInteger row = [indexPath row];
NSDictionary *rowData = [self.dataArray objectAtIndex:row];
//NSLog(#"%#",rowData);
cell.text = [rowData objectForKey:#"ename"];
cell.labelName.text= [rowData objectForKey:#"ename"];
return cell;
}
I believe your problem is that you are not referring to dataArray as self.dataArray all the time which may cause your program not to work properly.
Then assign via
cell.textLabel.text = [self.dataArray objectAtIndex:indexRow.row];
Hope this helped
Seb Kade
"I'm here to help"
Apple's SeismicXML app does exactly this. Look at the rootViewController's cellForRowAtIndexPath.
Also, make sure your tableview has it's delegate and datasource set correctly in Interface Builder (if you chose to use it).