I'm trying to write a simple RSS reader for the iPhone, and it appeared to be working fine, until I started working with Instruments, and discovered my App is leaking massive amounts of memory.
I'm using the NSXMLParser class to parse an RSS feed. My memory leaks appear to be originating from the overridden delegate methods:
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
and
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
I'm also suspicious of the code that populates the cells from my parsed data, I've included the code from those methods and a few other key ones, any insights would be greatly appreciated.
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if ([self.currentElement isEqualToString:#"title"]) {
[self.currentTitle appendString:string];
} else if ([self.currentElement isEqualToString:#"link"]) {
[self.currentURL appendString:string];
} else if ([self.currentElement isEqualToString:#"description"]) {
[self.currentSummary appendString:string];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
if ([elementName isEqualToString:#"item"]) {
//asdf
NSMutableDictionary *item = [[NSMutableDictionary alloc] init];
[item setObject:currentTitle forKey:#"title"];
[item setObject:currentURL forKey:#"URL"];
[item setObject:currentSummary forKey:#"summary"];
[self.currentTitle release];
[self.currentURL release];
[self.currentSummary release];
[self.stories addObject:item];
[item release];
}
}
// Customize the appearance of table view cells.
- (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];
}
// Configure the cell.
// Set up the cell
int index = [indexPath indexAtPosition: [indexPath length] - 1];
CGRect contentRect = CGRectMake(8.0, 4.0, 260, 20);
UILabel *textLabel = [[UILabel alloc] initWithFrame:contentRect];
if (self.currentLevel == 0) {
textLabel.text = [self.categories objectAtIndex: index];
} else {
textLabel.text = [[self.stories objectAtIndex: index] objectForKey:#"title"];
}
textLabel.textColor = [UIColor blackColor];
textLabel.font = [UIFont boldSystemFontOfSize:14];
[[cell contentView] addSubview: textLabel];
//[cell setText:[[stories objectAtIndex: storyIndex] objectForKey: #"title"]];
[textLabel autorelease];
return cell;
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
if ([elementName isEqualToString:#"item"]) {
self.currentTitle = [[NSMutableString alloc] init];
self.currentURL = [[NSMutableString alloc] init];
self.currentSummary = [[NSMutableString alloc] init];
}
if (currentElement != nil) {
[self.currentElement release];
}
self.currentElement = [elementName copy];
}
- (void)dealloc {
[currentElement release];
[currentTitle release];
[currentURL release];
[currentSummary release];
[currentDate release];
[stories release];
[rssParser release];
[storyTable release];
[super dealloc];
}
// Override to support row selection in the table view.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Navigation logic may go here -- for example, create and push another view controller.
// AnotherViewController *anotherViewController = [[AnotherViewController alloc] initWithNibName:#"AnotherView" bundle:nil];
int index = [indexPath indexAtPosition: [indexPath length] - 1];
if (currentLevel == 1) {
StoryViewController *storyViewController = [[StoryViewController alloc] initWithURL:[[stories objectAtIndex: index] objectForKey:#"URL"] nibName:#"StoryViewController" bundle:nil];
[self.navigationController pushViewController:storyViewController animated:YES];
[storyViewController release];
} else {
RootViewController *rvController = [[RootViewController alloc] initWithNibName:#"RootViewController" bundle:nil];
rvController.currentLevel = currentLevel + 1;
rvController.rssIndex = index;
[self.navigationController pushViewController:rvController animated:YES];
[rvController release];
}
}
I figured out my problem, all of my memory leaks stemmed from this statement:
self.stories = [[NSMutableArray alloc] init];
This causes the retain count of stories to be incremented by 2, since the setter calls retain on the newly allocated array.
I replaced the above statement with this one and it solved my problem:
NSMutableArray *array = [[NSMutableArray alloc] init];
self.stories = array;
[array release];
Another way of fixing your code is this replacing
self.stories = [NSMutableArray alloc] init];
with
self.stories = [NSMutableArray arrayWithCapacity:10];
The arrayWithCapacity method is autoreleased so you don't need to manually call release. (This is true for other classes i.e. setWithCapacity, stringWithFormat etc)
Thanks, Sam
PS Not helping your question but these lines look a little unusual :
[self.currentTitle release];
You should probably be doing this :
self.currentTitle = nil;
That will release currentTitle the same as your code does but it will also set it to nil which means you can't use it again by mistake!
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.
My UITableView is not displaying all values after parsing XML. It returns only one row. After parsing xml, why is only one row being shown and not the whole ArrayList? I have checked my xml php page. It is showing all values fine.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[xmlcont xmlbanktransfer] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSUInteger const kMagnitudeImageTag = 0;
static NSUInteger const kLocationLabelTag = 4;
static NSUInteger const klocationtag = 6;
static NSUInteger const kacctag = 8;
static NSUInteger const knameLabelTag = 9;
UIImageView *magnitudeImage = nil;
UILabel*locationLabel = nil;
UILabel*locationtag=nil;
UILabel*acc=nil;
UILabel*nameLabel= nil;
//NSMutableArray *cont = [xmlcont tweets];
// Tweet *current = [cont objectAtIndex:indexPath.row];
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
/*//common settings
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
cell.imageView.contentMode = UIViewContentModeScaleAspectFill;
cell.imageView.frame = CGRectMake(0.0f, 0.0f, 44.0f, 44.0f);
cell.imageView.clipsToBounds = YES;
*/
}
for(UIView *view in cell.contentView.subviews)
{
if ([view isKindOfClass:[UIView class]])
{
[view removeFromSuperview];
}
}
NSMutableArray *cont = [xmlcont xmlbanktransfer];
trans *current= [cont objectAtIndex:indexPath.row];
NSLog(#"sd %#",current.date);
NSLog(#"sd %#",current.name);
locationLabel = [[UILabel alloc] initWithFrame:CGRectMake(5,10, 250, 20)];
locationLabel.tag = kLocationLabelTag;
locationLabel.font = [UIFont boldSystemFontOfSize:15];
[cell.contentView addSubview:locationLabel];
locationLabel.text=current.name;
locationLabel.textColor=[UIColor colorWithRed:0.050 green:0.278 blue:0.392 alpha:1];
//locationLabel.backgroundColor=[UIColor lightGrayColor];
locationLabel.backgroundColor=[UIColor colorWithRed:225 green:225 blue:225 alpha:0] ;
nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(180,10, 250, 20)];
nameLabel.tag = knameLabelTag;
nameLabel.font = [UIFont systemFontOfSize:13];
[cell.contentView addSubview:nameLabel];
nameLabel.text=current.date ;
nameLabel.textColor=[UIColor colorWithRed:0.050 green:0.278 blue:0.392 alpha:1];
//locationLabel.backgroundColor=[UIColor lightGrayColor];
nameLabel.backgroundColor=[UIColor colorWithRed:225 green:225 blue:225 alpha:0] ;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
code for parsing xml:
xmlbanktransfer=[[NSMutableArray alloc] init];
NSURL *url=[NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
parser=[[NSXMLParser alloc] initWithContentsOfURL:url];
[parser setDelegate:self];
[parser parse];
NSLog(#"testing12 %# ",url);
// NSLog(#"tweets %# ", xmlbanktransfer);
NSLog(#"Total values = %d",[xmlbanktransfer count]);
return self;
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
if([elementName isEqualToString:#"item"])
{
currentTweet = [trans alloc];
banktransNodeContent =[[NSMutableString alloc] init];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if([elementName isEqualToString:#"date"])
{
currentTweet.date = [currentTweet.date stringByReplacingOccurrencesOfString:#"&" withString:#" "];
currentTweet.date = banktransNodeContent;
}
if([elementName isEqualToString:#"name"])
{
currentTweet.name =banktransNodeContent;
}
if ([elementName isEqualToString:#"type"])
{
currentTweet.type=banktransNodeContent;
}
if ([elementName isEqualToString:#"gross"])
{
currentTweet.gross=banktransNodeContent;
}
if ([elementName isEqualToString:#"fee"])
{
currentTweet.fee=banktransNodeContent;
}
if ([elementName isEqualToString:#"net"])
{
currentTweet.net=banktransNodeContent;
NSLog(#"current tweet %#",currentTweet.net);
}
if ([elementName isEqualToString:#"category"])
{
currentTweet.category=banktransNodeContent;
NSLog(#"current tweet %#",currentTweet.category);
}
if ([elementName isEqualToString:#"account"])
{
currentTweet.account=banktransNodeContent;
NSLog(#"current tweet %#",currentTweet.account);
}
if([elementName isEqualToString:#"item"])
{
[xmlbanktransfer addObject:currentTweet];
currentTweet = nil;
banktransNodeContent = nil;
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
NSLog(#"currentNodeContent are %#",banktransNodeContent);
banktransNodeContent = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSLog(#"currentNodeContentstring test are %#",banktransNodeContent);
}
- (void)parser:(NSXMLParser *)parser foundCDATA:(NSData *)CDATABlock
{
banktransNodeContent = [[NSString alloc] initWithData:CDATABlock encoding:NSUTF8StringEncoding];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[xmlcont xmlbanktransfer] count];
}
this method tells the tableview how many cells to populate
Log the value and see how much it is returning [it must be 1 returning now,since the table shows one row].Correct the return value and you have all values displayed
Things to check
Returning value mentioned above
Make sure the array xmlbanktransfer is a property which is of strong type
I am newer in iPhone application development. I want to find out why tableview cell is not showing data. I tried a lot of ways. I am giving my code below.
Note that I am seeing data at my console which is coming from XML file but it's not displaying in UITableView cell.
#synthesize newsTable;
#synthesize activityIndicator;
#synthesize rssParser;
#synthesize stories;
#synthesize item;
#synthesize currentElement;
#synthesize currentTitle, currentDate, currentSummary, currentLink;
// The designated initializer. Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
/*
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization.
}
return self;
}
*/
#pragma mark -
#pragma mark Parsing
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
if ([stories count] == 0) {
NSString * path = #"http://icms7.bitmascot.com:8080/webcommander2.0S2/rest/services/catalogue/getAllDummyCategoryProduct";
[self parseXMLFileAtURL:path];
}
cellSize = CGSizeMake([newsTable bounds].size.width, 60);
}
- (void)parseXMLFileAtURL:(NSString *)URL
{
stories = [[NSMutableArray alloc] init];
//you must then convert the path to a proper NSURL or it won't work
NSURL *xmlURL = [NSURL URLWithString:URL];
// here, for some reason you have to use NSClassFromString when trying to alloc NSXMLParser, otherwise you will get an object not found error
// this may be necessary only for the toolchain
rssParser = [[NSXMLParser alloc] initWithContentsOfURL:xmlURL];
// Set self as the delegate of the parser so that it will receive the parser delegate methods callbacks.
[rssParser setDelegate:self];
// Depending on the XML document you're parsing, you may want to enable these features of NSXMLParser.
[rssParser setShouldProcessNamespaces:NO];
[rssParser setShouldReportNamespacePrefixes:NO];
[rssParser setShouldResolveExternalEntities:NO];
[rssParser parse];
}
- (void)parserDidStartDocument:(NSXMLParser *)parser
{
NSLog(#"found file and started parsing");
}
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
{
NSString * errorString = [NSString stringWithFormat:#"Unable to download story feed from web site (Error code %i )", [parseError code]];
NSLog(#"error parsing XML: %#", errorString);
UIAlertView * errorAlert = [[UIAlertView alloc] initWithTitle:#"Error loading content" message:errorString delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[errorAlert show];
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
NSLog(#"found this element: %#", elementName);
currentElement = [elementName copy];
if ([elementName isEqualToString:#"ProductData"])
{
// clear out our story item caches...
item = [[NSMutableDictionary alloc] init];
currentTitle = [[NSMutableString alloc] init];
currentDate = [[NSMutableString alloc] init];
currentSummary = [[NSMutableString alloc] init];
currentLink = [[NSMutableString alloc] init];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
//NSLog(#"ended element: %#", elementName);
if ([elementName isEqualToString:#"ProductData"])
{ // save values to an item, then store that item into the array...
[item setObject:currentTitle forKey:#"id"];
[item setObject:currentLink forKey:#"productNumber"];
[item setObject:currentSummary forKey:#"name"];
[item setObject:currentDate forKey:#"dateCreated"];
[stories addObject:[item copy]];
NSLog(#"adding story: %#", currentTitle);
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
NSLog(#"found characters: %#", string);
// save the characters for the current item...
if ([currentElement isEqualToString:#"ProductData"])
{
[currentTitle appendString:string];
}
else if ([currentElement isEqualToString:#"id"])
{
[currentLink appendString:string];
}
else if ([currentElement isEqualToString:#"ProductNumber"])
{
[currentSummary appendString:string];
}
else if ([currentElement isEqualToString:#"dateCreatrd"])
{
[currentDate appendString:string];
}
}
- (void)parserDidEndDocument:(NSXMLParser *)parser {
[activityIndicator stopAnimating];
[activityIndicator removeFromSuperview];
NSLog(#"all done!");
NSLog(#"stories array has %d items", [stories count]);
NSLog(#"data in stories: %#",[stories description]);
[newsTable reloadData];
}
#pragma mark tableView
- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section
{
return [stories count];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
{
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier: MyIdentifier];
}
// Set up the cell
int storyIndex = [indexPath indexAtPosition: [indexPath length] - 1];
//[cell setText:[[stories objectAtIndex: storyIndex] objectForKey: #"title"]];
//[cell setLabelText:[[stories objectAtIndex:storyIndex] objectForKey: #"ProductData"]];
//[cell setText:[stories objectAtIndex:storyIndex]];
cell.textLabel.text = [stories objectAtIndex:storyIndex];
NSLog(#"%# ",cell.textLabel.text);
//cell.detailTextLabel.text = [stories objectAtIndex:indexPath.row];
return cell;
}
/*
- (void)setLabelText:(NSString *)_text{
UILabel *cellText;
cellText.text= _text;
[cellText sizeToFit];
}
*/
/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations.
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc. that aren't in use.
}
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[currentElement release];
[rssParser release];
[stories release];
[item release];
[currentTitle release];
[currentDate release];
[currentSummary release];
[currentLink release];
[super dealloc];
}
#end
Try to set value of property textLabel, not detailedTextLabel :
cell.textLabel.text = [[stories objectAtIndex:storyIndex] valueForKey:#"productNumber"];
Also try to create cell using predefined styles:
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier: MyIdentifier];
To make a cell you should use
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
method. By default the detailTextLabel is not visible in the cell.
Try to use other styles - UITableViewCellStyleValue1, for example.
Instead of giving,
int storyIndex = [indexPath indexAtPosition: [indexPath length] - 1];
//[cell setText:[[stories objectAtIndex: storyIndex] objectForKey: #"title"]];
//[cell setLabelText:[[stories objectAtIndex:storyIndex] objectForKey: #"ProductData"]];
//[cell setText:[stories objectAtIndex:storyIndex]];
cell.detailTextLabel.text = [stories objectAtIndex:storyIndex];
try this code:
cell.detailTextLabel.text = [stories objectAtIndex:indexPath.row];
before that ,just check your array(stories)having content?
Thank You..
cell.detailTextLabel.text = [stories objectAtIndex:storyIndex];
replace above statement with belo wstatement iy will work i think
cell.detailTextLabel.text = [stories objectAtIndex:indexPath.row];
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).