I have a number of blog apps. Recently, some of them started experiencing some issues. I use ASIHTTP Classes and GDataXML Classes to parse the xml of a wordpress feed, and put each item (article) into a mutable array. The tableview is then supposed to load all of the stories into a cell for each article. The issue I am having is that new articles are not being displayed on first run, the user is having to Pull to Refresh, and then the new article displays. I ran a test just now on an app. The article was posted a few hours ago. I ran the app, it wasn't there. Pulled to refresh, it showed. Closed down the app completely, restarted it, and it was gone again. Here is the code in the TableView's implementation:
#implementation RootViewController
- (void)refresh {
self.allEntries = [NSMutableArray array];
self.queue = [[[NSOperationQueue alloc] init] autorelease];
self.feeds = [NSArray arrayWithObjects:#"http://bubblycandacebabbles.wordpress.com/?cat=-2008&feed=rss2",
nil];
for (NSString *feed in _feeds) {
NSURL *url = [NSURL URLWithString:feed];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDelegate:self];
[_queue addOperation:request];
}
}
- (void)viewDidLoad {
[super viewDidLoad];
[activity startAnimating];
//[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:#"navbarcopy.png"] forBarMetrics:UIBarMetricsDefault];
self.title = #"Blog";
CGFloat nRed=111.0/255.0;
CGFloat nBlue=209/255.0;
CGFloat nGreen=229.0/255.0;
UIColor *myColor=[[UIColor alloc]initWithRed:nRed green:nBlue blue:nGreen alpha:1];
UIBarButtonItem *font = [[UIBarButtonItem alloc] initWithTitle:#"Change Font Size" style:UIBarButtonItemStylePlain target:self action:#selector(fontsizes)];
self.navigationController.navigationItem.rightBarButtonItem = font;
self.tableView.backgroundColor = myColor;
self.refreshControl = [[UIRefreshControl alloc] init];
[self.refreshControl addTarget:self action:#selector(refreshInvoked:forState:) forControlEvents:UIControlEventValueChanged];
[self refresh];
}
-(void) refreshInvoked:(id)sender forState:(UIControlState)state {
// Refresh table here...
[_allEntries removeAllObjects];
[self.tableView reloadData];
[self refresh];
}
- (void)parseRss:(GDataXMLElement *)rootElement entries:(NSMutableArray *)entries {
NSArray *channels = [rootElement elementsForName:#"channel"];
for (GDataXMLElement *channel in channels) {
NSString *blogTitle = [channel valueForChild:#"title"];
NSArray *items = [channel elementsForName:#"item"];
for (GDataXMLElement *item in items) {
NSString *articleTitle = [item valueForChild:#"title"];
NSString *articleUrl = [item valueForChild:#"link"];
NSString *articleDateString = [item valueForChild:#"pubDate"];
NSDate *articleDate = [NSDate dateFromInternetDateTimeString:articleDateString formatHint:DateFormatHintRFC822];
NSString *articleImage = [item valueForChild:#"content:encoded"];
NSScanner *theScanner;
NSString *gt =nil;
theScanner = [NSScanner scannerWithString:articleImage];
NSString *comments = [articleUrl stringByAppendingString:#"#respond"];
NSString *commentslink = [NSString stringWithFormat: #"Leave A Comment",comments];
// find start of tag
[theScanner scanUpToString:#"alt=\"\" width=" intoString:NULL] ;
// find end of tag
[theScanner scanUpToString:#"/>" intoString:>] ;
// replace the found tag with a space
//(you can filter multi-spaces out later if you wish)
NSString *test = [articleImage stringByReplacingOccurrencesOfString:[ NSString stringWithFormat:#"%#", gt] withString:#"alt=\"\" width=\"150\" height=\"150\""];
NSString *final = [test stringByReplacingOccurrencesOfString:#"float:none;height:30px" withString:#"float:none;height:1px"];
NSDateFormatter * dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setTimeStyle:NSDateFormatterShortStyle];
[dateFormatter setDateStyle:NSDateFormatterShortStyle];
NSString *dateofarticle = [dateFormatter stringFromDate:articleDate];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *smalltitle = [defaults objectForKey:#"Title"];
NSString *smallbody = [defaults objectForKey:#"Article"];
NSString *bodyoftext = [[[[[[[[[[[#"<head><body bgcolor=\"#6fd1e5\" text=\"#CC0099\"><style type='text/css'>a > img {pointer-events: none;cursor: default;max-width: 310;}</style></head><b><font size=" stringByAppendingString: smalltitle ] stringByAppendingString:#"><div align=\"left\"><FONT FACE=\"noteworthy\">" ]stringByAppendingString:articleTitle] stringByAppendingString:#"</font></b><font size=" ] stringByAppendingString:smallbody ] stringByAppendingString:#"><div align=\"left\"><FONT FACE=\"noteworthy\">"] stringByAppendingString:dateofarticle] stringByAppendingString:#"</div></p><FONT FACE=\"noteworthy\">"] stringByAppendingString:final] stringByAppendingString:commentslink]stringByAppendingString:#"</FONT>"];
RSSEntry *entry = [[[RSSEntry alloc] initWithBlogTitle:blogTitle
articleTitle:articleTitle
articleUrl:articleUrl
articleDate:articleDate
articleImage:bodyoftext] autorelease];
[entries addObject:entry];
}
}
}
- (void)parseFeed:(GDataXMLElement *)rootElement entries:(NSMutableArray *)entries {
if ([rootElement.name compare:#"rss"] == NSOrderedSame) {
[self parseRss:rootElement entries:entries];
} else if ([rootElement.name compare:#"feed"] == NSOrderedSame) {
[self parseAtom:rootElement entries:entries];
} else {
NSLog(#"Unsupported root element: %#", rootElement.name);
}
}
// Customize the number of sections in the table view.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [_allEntries count];
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
Cell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[Cell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
RSSEntry *entry = [_allEntries objectAtIndex:indexPath.row];
NSString *substring = #"http://bubblycandacebabbles.files.wordpress.com";
NSRange textRange = [entry.articleImage rangeOfString:substring];
if(textRange.location != NSNotFound){
NSString *thearticleImage = entry.articleImage;
NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:#"src=\"([^\"]+)\"" options:NSRegularExpressionCaseInsensitive error:NULL];
NSString *someString = thearticleImage;
NSString *oneurl = [someString substringWithRange:[expression rangeOfFirstMatchInString:someString options:NSMatchingCompleted range:NSMakeRange(0, [someString length])]];
NSString *finalstring = [oneurl stringByReplacingOccurrencesOfString:#"src=\"" withString:#""];
NSString *thefinalstring = [finalstring stringByReplacingOccurrencesOfString:#"\"" withString:#""];
NSDateFormatter * dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setTimeZone:[NSTimeZone localTimeZone]];
[dateFormatter setTimeStyle:NSDateFormatterShortStyle];
[dateFormatter setDateStyle:NSDateFormatterShortStyle];
CGFloat nRed=204.0/255.0;
CGFloat nBlue=0/255.0;
CGFloat nGreen=153.0/255.0;
UIColor *myColortext=[[UIColor alloc]initWithRed:nRed green:nBlue blue:nGreen alpha:1];
NSString *articleDateString = [dateFormatter stringFromDate:entry.articleDate];
UIFont *cellFont = [UIFont fontWithName:#"noteworthy" size:16];
UIFont *cellFont2 = [UIFont fontWithName:#"noteworthy" size:12];
CALayer * l = [cell.imageView layer];
[l setMasksToBounds:YES];
[l setCornerRadius:11];
[l setBorderWidth:2.0];
[l setBorderColor:[[UIColor blackColor] CGColor]];
cell.textLabel.text = entry.articleTitle;
cell.textLabel.numberOfLines = 2;
cell.detailTextLabel.adjustsFontSizeToFitWidth = YES;
cell.detailTextLabel.text = [NSString stringWithFormat:#"%# - Mother May I Blog", articleDateString];
cell.textLabel.font = cellFont;
cell.detailTextLabel.font = cellFont2;
cell.textLabel.textColor = myColortext;
cell.detailTextLabel.textColor = myColortext;
[cell.imageView setImageWithURL:[NSURL URLWithString:thefinalstring] placeholderImage:[UIImage imageNamed:#"iphoneicon#2x.png"]];
}
else {
CALayer * l = [cell.imageView layer];
[l setMasksToBounds:YES];
[l setCornerRadius:11];
[l setBorderWidth:2.0];
[l setBorderColor:[[UIColor blackColor] CGColor]];
NSDateFormatter * dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setTimeZone:[NSTimeZone localTimeZone]];
[dateFormatter setTimeStyle:NSDateFormatterShortStyle];
[dateFormatter setDateStyle:NSDateFormatterShortStyle];
NSString *articleDateString = [dateFormatter stringFromDate:entry.articleDate];
UIFont *cellFont = [UIFont fontWithName:#"noteworthy" size:16];
UIFont *cellFont2 = [UIFont fontWithName:#"noteworthy" size:12];
cell.imageView.image = [UIImage imageNamed:#"iphoneicon#2x.png"];
cell.textLabel.text = entry.articleTitle;
cell.textLabel.numberOfLines = 2;
cell.detailTextLabel.adjustsFontSizeToFitWidth = YES;
cell.detailTextLabel.text = [NSString stringWithFormat:#"%# - Mother May I Blog", articleDateString];
CGFloat nRed=204.0/255.0;
CGFloat nBlue=0/255.0;
CGFloat nGreen=153.0/255.0;
UIColor *myColortext=[[UIColor alloc]initWithRed:nRed green:nBlue blue:nGreen alpha:1];
cell.textLabel.font = cellFont;
cell.detailTextLabel.font = cellFont2;
cell.textLabel.textColor = myColortext;
cell.detailTextLabel.textColor = myColortext;
}
return cell;
}
You need to invoke
[self.tableView reloadData];
at some point after your data has finished loading. How exactly you do this is a bit tricky, you need some way of telling when your operation queue is empty. Alternatively, you could theoretically call it after each operation in the queue is complete, that way the table will populate one at a time. This could cause problems if the user is on a slow connection, as reloading the table can cause jumps in the user experience, and I'm not positive on the thread safety of calling reloadData from a different thread
Related
In my app, I use Parse. I have it set up like this:
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
// The className to query on
self.parseClassName = #"Prayers";
// Whether the built-in pull-to-refresh is enabled
self.pullToRefreshEnabled = YES;
// Whether the built-in pagination is enabled
self.paginationEnabled = YES;
// The number of objects to show per page
self.objectsPerPage = 20;
}
return self;
}
- (PFQuery *)queryForTable {
PFQuery *query = [PFQuery queryWithClassName:#"Prayers"];
// If no objects are loaded in memory, we look to the cache first to fill the table
// and then subsequently do a query against the network.
if (self.objects.count == 0) {
query.cachePolicy = kPFCachePolicyCacheThenNetwork;
}
[query orderByDescending:#"createdAt"];
return query;
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
object:(PFObject *)object
{
static NSString *CellIdentifier = #"Cell";
Cell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[Cell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
self.theObject = object;
BOOL anony = [object[#"Anonymous"] boolValue];
if (!anony) {
NSString *names = [[object[#"FirstName"] stringByAppendingString:#" "] stringByAppendingString:object[#"LastName"]];
cell.profileName.text = names;
cell.contentLabel.text = object[#"Request"];
cell.firstName = object[#"FirstName"];
cell.lastName = object[#"LastName"];
cell.iostoken = object[#"DeviceID"];
cell.request = names;
cell.prayerObject = object;
PFFile *thumbnail = object[#"ProfilePic"];
cell.profilePic.image = [UIImage imageNamed:#"AppIcon60x60#2x.png"];
/*[cell.commentButton addTarget:self action:#selector(didTapCommentButtonAction:) forControlEvents:UIControlEventTouchUpInside];
[cell.commentButton setTitle:#"Share" forState:UIControlStateNormal];
[cell.commentButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[cell.commentButton setTitleColor:[UIColor greenColor] forState:UIControlStateHighlighted];*/
[thumbnail getDataInBackgroundWithBlock:^(NSData *imageData, NSError *error) {
UIImage *thumbnailImage = [UIImage imageWithData:imageData];
UIImageView *thumbnailImageView = [[UIImageView alloc] initWithImage:thumbnailImage];
cell.profilePic.image = thumbnailImage;
}];
NSString *dates = object[#"dateMade"];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"MMM_dd_yyyy"];
NSDate *datefromstring = [formatter dateFromString:dates];
NSDateFormatter *formatter2 = [[NSDateFormatter alloc] init];
[formatter2 setDateFormat:#"MMM dd, yyyy"];
cell.dateLabel.text = [formatter2 stringFromDate:datefromstring];
UIFont *cellFont = [UIFont fontWithName:#"Verdana-Bold" size:15];
UIFont *cellFont2 = [UIFont fontWithName:#"Verdana-Bold" size:12];
}
else {
// Configure the cell to show todo item with a priority at the bottom
cell.profileName.text = object[#"Title"];
cell.contentLabel.text = object[#"Request"];
cell.firstName = object[#"FirstName"];
cell.lastName = object[#"LastName"];
cell.iostoken = object[#"DeviceID"];
cell.request = object[#"Title"];
cell.prayerObject = object;
PFFile *thumbnail = object[#"ProfilePic"];
cell.profilePic.image = [UIImage imageNamed:#"AppIcon60x60#2x.png"];
[thumbnail getDataInBackgroundWithBlock:^(NSData *imageData, NSError *error) {
UIImage *thumbnailImage = [UIImage imageWithData:imageData];
UIImageView *thumbnailImageView = [[UIImageView alloc] initWithImage:thumbnailImage];
cell.profilePic.image = thumbnailImage;
}];
NSString *dates = object[#"dateMade"];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"MMM_dd_yyyy"];
NSDate *datefromstring = [formatter dateFromString:dates];
NSDateFormatter *formatter2 = [[NSDateFormatter alloc] init];
[formatter2 setDateFormat:#"MMM dd, yyyy"];
cell.dateLabel.text = [formatter2 stringFromDate:datefromstring];
}
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
PFObject *entry = [self.objects objectAtIndex:indexPath.row];
NSString *commentString = entry[#"Request"];
NSString *nameString = #"";
NSLog(#"%#", commentString);
return [Cell heightForCellWithContentString:(NSString *)commentString] +25 ;
}
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 30200
if( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad )
{
if (_webViewController2 == nil) {
self.webViewController2 = [[[WebViewController2 alloc] initWithNibName:#"WebViewController2" bundle:[NSBundle mainBundle]] autorelease];
}
RSSEntry *entry = [_allEntries objectAtIndex:indexPath.row];
_webViewController2.entry = entry;
[self.navigationController pushViewController:_webViewController2 animated:YES];
[self.objects objectAtIndex:indexPath.row];
}
else {
PFObject *entry = [self.objects objectAtIndex:indexPath.row];
if (_webViewController == nil) {
self.webViewController = [[[WebViewController alloc] initWithNibName:#"WebViewController" bundle:[NSBundle mainBundle]] autorelease];
}
_webViewController.finalObject = entry;
[self.navigationController pushViewController:_webViewController animated:YES];
}
#endif
}
As I understand, that should load up 20 items at a time, and when you scroll to the end of those, load up the next 20. However, once I have 20 items, the app crashes, and I get this message:
Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 20 beyond bounds [0 .. 19]'
After putting an exception breakpoint in, the line causing the error is in the heightForRow method
PFObject *entry = [self.objects objectAtIndex:indexPath.row];
What's going on?
I have a PFQueryTableViewController in my app. If it is a root view of a controller, it is fine. However, if I push it onto another view, there is a strange line that goes through the top of each cell.
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
// The className to query on
self.parseClassName = #"Prayers";
// Whether the built-in pull-to-refresh is enabled
self.pullToRefreshEnabled = YES;
// Whether the built-in pagination is enabled
self.paginationEnabled = YES;
// The number of objects to show per page
self.objectsPerPage = 20;
}
return self;
}
- (PFQuery *)queryForTable {
PFQuery *query = [PFQuery queryWithClassName:self.parseClassName];
// If no objects are loaded in memory, we look to the cache first to fill the table
// and then subsequently do a query against the network.
if (self.objects.count == 0) {
query.cachePolicy = kPFCachePolicyCacheThenNetwork;
}
[query orderByDescending:#"createdAt"];
return query;
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
object:(PFObject *)object
{
static NSString *CellIdentifier = #"Cell";
Cell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[Cell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
self.theObject = object;
// Configure the cell to show todo item with a priority at the bottom
cell.profileName.text = object[#"Title"];
cell.contentLabel.text = object[#"Request"];
cell.firstName = object[#"FirstName"];
cell.lastName = object[#"LastName"];
cell.iostoken = object[#"DeviceID"];
cell.request = object[#"Title"];
cell.prayerObject = object;
PFFile *thumbnail = object[#"ProfilePic"];
cell.profilePic.image = [UIImage imageNamed:#"AppIcon60x60#2x.png"];
[cell.commentButton addTarget:self action:#selector(didTapCommentButtonAction:) forControlEvents:UIControlEventTouchUpInside];
[cell.commentButton setTitle:#"Share" forState:UIControlStateNormal];
[cell.commentButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[cell.commentButton setTitleColor:[UIColor greenColor] forState:UIControlStateHighlighted];
[thumbnail getDataInBackgroundWithBlock:^(NSData *imageData, NSError *error) {
UIImage *thumbnailImage = [UIImage imageWithData:imageData];
UIImageView *thumbnailImageView = [[UIImageView alloc] initWithImage:thumbnailImage];
cell.profilePic.image = thumbnailImage;
}];
NSString *dates = object[#"dateMade"];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"MMM_dd_yyyy"];
NSDate *datefromstring = [formatter dateFromString:dates];
NSDateFormatter *formatter2 = [[NSDateFormatter alloc] init];
[formatter2 setDateFormat:#"MMM dd, yyyy"];
cell.dateLabel.text = [formatter2 stringFromDate:datefromstring];
UIFont *cellFont = [UIFont fontWithName:#"Verdana-Bold" size:15];
UIFont *cellFont2 = [UIFont fontWithName:#"Verdana-Bold" size:12];
return cell;
}
Just having this as root view presents this:
If I present it from another view like this:
-(void)myPrayers {
BlogView1 *prayers = [[BlogView1 alloc] init];
[self.navigationController pushViewController:prayers animated:YES];
}
It looks like this:
That looks like a UITableViewCellSeperatorStyle Property needing to be set to UITableViewCellSeparatorStyleNone...
[_table setSeparatorStyle:UITableViewCellSeparatorStyleNone];
OR
set the separator color of your UITableViewCell to clear color
[_table setSeparatorColor:<#(UIColor *)#>]
I have a simple blog app that lists the articles on the main screen as a UITableView. Everything looks fine when first loading, but when I scroll down and back up, it redraws the cells wrong, and...well, just check out this picture.
The code I use for the cells is listed below. What am I doing incorrect?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
Cell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[Cell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
RSSEntry *entry = [_allEntries objectAtIndex:indexPath.row];
NSString *substring = #"http://316apps.com/ipreachersblog/wp";
NSRange textRange = [entry.articleImage rangeOfString:substring];
NSString *substring2 = #"http://ipreacher.files.wordpress.com";
NSRange textRange2 = [entry.articleImage rangeOfString:substring2];
if(textRange.location != NSNotFound){
NSString *thearticleImage = entry.articleImage;
NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:#"src=\"([^\"]+)\"" options:NSRegularExpressionCaseInsensitive error:NULL];
NSString *someString = thearticleImage;
NSString *oneurl = [someString substringWithRange:[expression rangeOfFirstMatchInString:someString options:NSMatchingCompleted range:NSMakeRange(0, [someString length])]];
NSString *finalstring = [oneurl stringByReplacingOccurrencesOfString:#"src=\"" withString:#""];
NSString *thefinalstring = [finalstring stringByReplacingOccurrencesOfString:#"\"" withString:#""];
NSDateFormatter * dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setTimeZone:[NSTimeZone localTimeZone]];
[dateFormatter setTimeStyle:NSDateFormatterShortStyle];
[dateFormatter setDateStyle:NSDateFormatterShortStyle];
NSString *articleDateString = [dateFormatter stringFromDate:entry.articleDate];
UIFont *cellFont = [UIFont fontWithName:#"Copperplate-Bold" size:21];
UIFont *cellFont2 = [UIFont fontWithName:#"Copperplate-Bold" size:18];
CALayer * l = [cell.imageView layer];
[l setMasksToBounds:YES];
[l setCornerRadius:30];
[l setBorderWidth:2.0];
[l setBorderColor:[[UIColor blackColor] CGColor]];
cell.textLabel.text = entry.articleTitle;
cell.textLabel.numberOfLines = 3;
cell.detailTextLabel.text = articleDateString;
cell.textLabel.font = cellFont;
cell.detailTextLabel.font = cellFont2;
[cell.imageView setImageWithURL:[NSURL URLWithString:thefinalstring] placeholderImage:[UIImage imageNamed:#"Icon-60#2x.png"]];
UIColor *bobcatred = UIColorFromRGB(0x841617);
cell.textLabel.textColor = bobcatred;
cell.backgroundColor = [UIColor lightGrayColor];
}
else if (textRange2.location != NSNotFound){
NSString *thearticleImage = entry.articleImage;
NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:#"src=\"([^\"]+)\"" options:NSRegularExpressionCaseInsensitive error:NULL];
NSString *someString = thearticleImage;
NSString *oneurl = [someString substringWithRange:[expression rangeOfFirstMatchInString:someString options:NSMatchingCompleted range:NSMakeRange(0, [someString length])]];
NSString *finalstring = [oneurl stringByReplacingOccurrencesOfString:#"src=\"" withString:#""];
NSString *thefinalstring = [finalstring stringByReplacingOccurrencesOfString:#"\"" withString:#""];
NSDateFormatter * dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setTimeZone:[NSTimeZone localTimeZone]];
[dateFormatter setTimeStyle:NSDateFormatterShortStyle];
[dateFormatter setDateStyle:NSDateFormatterShortStyle];
NSString *articleDateString = [dateFormatter stringFromDate:entry.articleDate];
UIFont *cellFont = [UIFont fontWithName:#"Copperplate-Bold" size:21];
UIFont *cellFont2 = [UIFont fontWithName:#"Copperplate-Bold" size:18];
CALayer * l = [cell.imageView layer];
[l setMasksToBounds:YES];
[l setCornerRadius:30];
[l setBorderWidth:2.0];
[l setBorderColor:[[UIColor blackColor] CGColor]];
cell.textLabel.text = entry.articleTitle;
cell.textLabel.numberOfLines = 3;
cell.detailTextLabel.text = articleDateString;
cell.textLabel.font = cellFont;
cell.detailTextLabel.font = cellFont2;
[cell.imageView setImageWithURL:[NSURL URLWithString:thefinalstring] placeholderImage:[UIImage imageNamed:#"Icon-60#2x.png"]];
UIColor *bobcatred = UIColorFromRGB(0x841617);
cell.textLabel.textColor = bobcatred;
cell.backgroundColor = [UIColor lightGrayColor];
}
else {
CALayer * l = [cell.imageView layer];
[l setMasksToBounds:YES];
[l setCornerRadius:30];
[l setBorderWidth:2.0];
[l setBorderColor:[[UIColor blackColor] CGColor]];
NSDateFormatter * dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setTimeZone:[NSTimeZone localTimeZone]];
[dateFormatter setTimeStyle:NSDateFormatterShortStyle];
[dateFormatter setDateStyle:NSDateFormatterShortStyle];
NSString *articleDateString = [dateFormatter stringFromDate:entry.articleDate];
UIFont *cellFont = [UIFont fontWithName:#"Copperplate-Bold" size:21];
UIFont *cellFont2 = [UIFont fontWithName:#"Copperplate-Bold" size:18];
cell.imageView.image = [UIImage imageNamed:#"Icon-60#2x.png"];
cell.textLabel.text = entry.articleTitle;
cell.detailTextLabel.text = articleDateString;
cell.textLabel.font = cellFont;
cell.detailTextLabel.font = cellFont2;
UIColor *bobcatred = UIColorFromRGB(0x841617);
cell.textLabel.textColor = bobcatred;
cell.textLabel.numberOfLines = 3;
cell.backgroundColor = [UIColor lightGrayColor];
}
return cell;
}
The cell is custom, its implementation is:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (void)layoutSubviews {
[super layoutSubviews];
self.imageView.frame = CGRectMake(1,6,60,60);
float limgW = self.imageView.image.size.width;
if(limgW > 0) {
self.textLabel.frame = CGRectMake(74,self.textLabel.frame.origin.y,self.textLabel.frame.size.width,self.textLabel.frame.size.height);
self.detailTextLabel.frame = CGRectMake(74,self.detailTextLabel.frame.origin.y,self.detailTextLabel.frame.size.width,self.detailTextLabel.frame.size.height);
}
}
#end
My TableView, which uses custom cells, sometimes 'stops' scrolling when I return from a DetailView.
I can push the view up a couple inches or so, and the lower cells do come into view, but the scrollview should be 4 or 5 windows in height.
The detail view is called through a segue. In addition to the back button, I also trigger a return with a swipe gesture. Either way it happens. - not all the time though.
Hope this is enough info. Does anyone have any ideas what I am screwing up?
Thanks!
Here's some code:
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath{
int row = [indexPath row];
int sect = [indexPath section];
NSDictionary *shift = [globals.shifts objectAtIndex:sect];
NSLog(#"\nShift = %#", shift);
NSLog(#"\nEmployees = %#", [shift objectForKey:#"Employees"]);
NSArray *employees = [shift objectForKey:#"Employees"];
NSDictionary *employee = [employees objectAtIndex:row];
globals.badge = [employee objectForKey:#"Badge"];
globals.name = [employee objectForKey:#"Name"];
return indexPath;
}
- (void)receivedData:(NSData *)responseData {
NSError* error;
globals.report = [NSJSONSerialization
JSONObjectWithData:responseData
options:kNilOptions
error:&error];
globals.shifts = [globals.report objectForKey:#"shifts"];
[globals.ai removeFromSuperview];
[table reloadData];
self.title = [ [NSString alloc] initWithFormat:#"%# - %#",
[globals.clientNames objectAtIndex:globals.curClient],
[self.dateFormatter stringFromDate: globals.weekEnd]];
self.title = [ [NSString alloc] initWithFormat:#"%#",
[self.dateFormatter stringFromDate: globals.weekEnd]];
}
-(void) viewWillAppear:(BOOL)animated {
if( globals == nil || globals.report == nil )
{
appDelegate = (MSIAppDelegate *)[[UIApplication sharedApplication] delegate];
globals = [appDelegate globals];
[[self view] addSubview:globals.ai];
NSString *urlString = [[NSString alloc] initWithFormat:
#"http://www.msiwebtrax.com/Client/%#/WeeklyReport?id=%#&start=%#&end=%#", [globals.clientIDs objectAtIndex:globals.curClient], globals.userName, [globals.formatter stringFromDate: globals.weekEnd], [globals.formatter stringFromDate: [globals.weekEnd dateByAddingTimeInterval:(-7) * 24 * 60 * 60] ]];
NSURL *url = [NSURL URLWithString: urlString];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^{
NSData* data = [NSData dataWithContentsOfURL:
url];
[self performSelectorOnMainThread:#selector(receivedData:)
withObject:data waitUntilDone:YES];
});
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
UIScrollView *tempScrollView=(UIScrollView *)self.view;
NSLog(#"scroll view dimensions: %f, %f", tempScrollView.contentSize.height, tempScrollView.contentSize.width);
self.dateFormatter = [[NSDateFormatter alloc] init];
[self.dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[self.dateFormatter setTimeStyle:NSDateFormatterNoStyle];
// Uncomment the following line to preserve selection between presentations.
self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
Here's the number of sections/rows
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
int sections = [globals.shifts count];
return sections;
}
- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSDictionary* shift = [globals.shifts objectAtIndex:section];
int rowCount = [[shift objectForKey:#"Employees"] count];
return rowCount;
}
--
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"EmployeeHoursCell";
EmployeeHoursCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if( cell == nil ) {
cell = [[EmployeeHoursCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
globals.employees = [[globals.shifts objectAtIndex:section] objectForKey:#"Employees"];
cell.Row.text = [[NSString alloc] initWithFormat:#"%3d", (row+1)];
cell.Id.text = [[globals.employees objectAtIndex:row] objectForKey:#"Badge"];
cell.Name.text = [[globals.employees objectAtIndex:row] objectForKey:#"Name"];
NSArray *days = [[globals.employees objectAtIndex:0] objectForKey:#"Days"];
cell.Hrs1.text = [[NSString alloc] initWithFormat:#"%#",[[days objectAtIndex:0] objectForKey:#"Rounded"] ];
cell.Hrs1.text = [[NSString alloc] initWithFormat:#"%.2f", [cell.Hrs1.text doubleValue]];
cell.Hrs2.text = [[NSString alloc] initWithFormat:#"%#",[[days objectAtIndex:1] objectForKey:#"Rounded"] ];
cell.Hrs2.text = [[NSString alloc] initWithFormat:#"%.2f", [cell.Hrs2.text doubleValue]];
cell.Hrs3.text = [[NSString alloc] initWithFormat:#"%#",[[days objectAtIndex:2] objectForKey:#"Rounded"] ];
cell.Hrs3.text = [[NSString alloc] initWithFormat:#"%.2f", [cell.Hrs3.text doubleValue]];
cell.Hrs4.text = [[NSString alloc] initWithFormat:#"%#",[[days objectAtIndex:3] objectForKey:#"Rounded"] ];
cell.Hrs4.text = [[NSString alloc] initWithFormat:#"%.2f", [cell.Hrs4.text doubleValue]];
cell.Hrs5.text = [[NSString alloc] initWithFormat:#"%#",[[days objectAtIndex:4] objectForKey:#"Rounded"] ];
cell.Hrs5.text = [[NSString alloc] initWithFormat:#"%.2f", [cell.Hrs5.text doubleValue]];
cell.Hrs6.text = [[NSString alloc] initWithFormat:#"%#",[[days objectAtIndex:5] objectForKey:#"Rounded"] ];
cell.Hrs6.text = [[NSString alloc] initWithFormat:#"%.2f", [cell.Hrs6.text doubleValue]];
cell.Hrs7.text = [[NSString alloc] initWithFormat:#"%#",[[days objectAtIndex:6] objectForKey:#"Rounded"] ];
cell.Hrs7.text = [[NSString alloc] initWithFormat:#"%.2f", [cell.Hrs7.text doubleValue]];
return cell;
}
Okay all - in the viewWillAppear method, I tried reloading the table, which didn't have any impact. But I then reset the contentSize to 0,0 before and it seems to work fine now, not entirely sure why - but I noticed the first time I come back from a detailview, the height is set to around 2000, the second time I return it is zero - at which point it works. So I set it to zero and reload.
Thanks Darren and all for the responses!
Using this tutorial, I made an iPhone blog app. It uses the count of the array created to setup the number of rows. I don't want to do every single item, because there are over 200 right now and growing. When I return any number for rows in section, it always crashes with the error about 0 beyond bounds of empty array. What else do I need to tweak from this tutorial to only allow the first 20 items to show in tableview?
UPDATE: I think I am making some progress. In the reqeustFinished method where it sorts the array, I edited it to make it this:
NSMutableArray *entries = [NSMutableArray array];
[self parseFeed:doc.rootElement entries:entries];
[entries removeLastObject];
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
for (RSSEntry *entry in entries) {
int insertIdx = [_allEntries indexForInsertingObject:entry sortedUsingBlock:^(id a, id b) {
RSSEntry *entry1 = (RSSEntry *) a;
RSSEntry *entry2 = (RSSEntry *) b;
return [entry1.articleDate compare:entry2.articleDate];
}];
NSLog(#"%#", entries);
[_allEntries insertObject:entry atIndex:insertIdx];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:insertIdx inSection:0]]
withRowAnimation:UITableViewRowAnimationRight];
Adding the line to removeLastObject for entries, removed the first item (which is ideally the ONLY one I would want on the first day). Are there other methods that would allow me to remove a range of objects at Index?
Here is the code I have for the Table View Class and DataSources.
- (void)refresh {
self.allEntries = [NSMutableArray array];
self.queue = [[[NSOperationQueue alloc] init] autorelease];
self.feeds = [NSArray arrayWithObjects:#"addressofxmlfile",
nil];
for (NSString *feed in _feeds) {
NSURL *url = [NSURL URLWithString:feed];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDelegate:self];
[_queue addOperation:request];
}
}
- (void)viewDidLoad {
[super viewDidLoad];
self.refreshControl = [[UIRefreshControl alloc] init];
[self.refreshControl addTarget:self action:#selector(refreshInvoked:forState:) forControlEvents:UIControlEventValueChanged];
[self refresh];
}
-(void) refreshInvoked:(id)sender forState:(UIControlState)state {
// Refresh table here...
[_allEntries removeAllObjects];
[self.tableView reloadData];
[self refresh];
}
- (void)parseRss:(GDataXMLElement *)rootElement entries:(NSMutableArray *)entries {
NSArray *channels = [rootElement elementsForName:#"channel"];
for (GDataXMLElement *channel in channels) {
NSString *blogTitle = [channel valueForChild:#"title"];
NSArray *items = [channel elementsForName:#"item"];
for (GDataXMLElement *item in items) {
NSString *articleTitle = [item valueForChild:#"title"];
NSString *articleUrl = [item valueForChild:#"guid"];
NSString *articleDateString = [item valueForChild:#"pubdate"];
NSDate *articleDate = [NSDate dateFromInternetDateTimeString:articleDateString formatHint:DateFormatHintRFC822];
NSString *articleImage = [item valueForChild:#"description"];
NSDateFormatter * dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setTimeStyle:NSDateFormatterShortStyle];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
NSString *dateofarticle = [dateFormatter stringFromDate:articleDate];
NSString *days = [articleImage substringFromIndex:7];
RSSEntry *entry = [[[RSSEntry alloc] initWithBlogTitle:blogTitle
articleTitle:articleTitle
articleUrl:articleUrl
articleDate:articleDate
articleImage:articleImage
date:thedate] autorelease];
[entries addObject:entry];
}
}
}
- (void)parseFeed:(GDataXMLElement *)rootElement entries:(NSMutableArray *)entries {
if ([rootElement.name compare:#"rss"] == NSOrderedSame) {
[self parseRss:rootElement entries:entries];
}else {
NSLog(#"Unsupported root element: %#", rootElement.name);
}
}
- (void)requestFinished:(ASIHTTPRequest *)request {
[_queue addOperationWithBlock:^{
NSError *error;
GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:[request responseData]
options:0 error:&error];
if (doc == nil) {
NSLog(#"Failed to parse %#", request.url);
} else {
NSMutableArray *entries = [NSMutableArray array];
[self parseFeed:doc.rootElement entries:entries];
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
for (RSSEntry *entry in entries) {
int insertIdx = [_allEntries indexForInsertingObject:entry sortedUsingBlock:^(id a, id b) {
RSSEntry *entry1 = (RSSEntry *) a;
RSSEntry *entry2 = (RSSEntry *) b;
return [entry1.articleDate compare:entry2.articleDate];
}];
[_allEntries insertObject:entry atIndex:insertIdx];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:insertIdx inSection:0]]
withRowAnimation:UITableViewRowAnimationRight];
}
}];
}
}];
[self.refreshControl endRefreshing];
}
- (void)requestFailed:(ASIHTTPRequest *)request {
NSError *error = [request error];
NSLog(#"Error: %#", error);
[self refresh];
}
#pragma mark -
#pragma mark Table view data source
// Customize the number of sections in the table view.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// [tableView setBackgroundColor:[UIColor redColor]];
return 1;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [_allEntries count];
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
Cell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[Cell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
RSSEntry *entry = [_allEntries objectAtIndex:indexPath.row];
CALayer * l = [cell.imageView layer];
[l setMasksToBounds:YES];
[l setCornerRadius:11];
[l setBorderWidth:2.0];
[l setBorderColor:[[UIColor blackColor] CGColor]];
NSDateFormatter * dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setTimeZone:[NSTimeZone localTimeZone]];
[dateFormatter setTimeStyle:NSDateFormatterShortStyle];
[dateFormatter setDateStyle:NSDateFormatterShortStyle];
NSString *articleDateString = [dateFormatter stringFromDate:entry.articleDate];
UIFont *cellFont = [UIFont fontWithName:#"Papyrus" size:19];
UIFont *cellFont2 = [UIFont fontWithName:#"Papyrus" size:17];
// cell.imageView.image = [UIImage imageNamed:#"icon#2x.png"];
cell.textLabel.text = entry.date;
cell.detailTextLabel.text = entry.articleTitle;
cell.detailTextLabel.textColor = [UIColor blackColor];
cell.textLabel.font = cellFont;
cell.detailTextLabel.font = cellFont2;
return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 73.4;
}
You are assigning allEntries to new Array in the Refresh method here:
- (void)refresh {
self.allEntries = [NSMutableArray array];
The tutorial only does this in the ViewDidLoad Method. Not sure if this is a problem as i don't know exactly when/how refresh is called.
Found this answer that shows how to hide cells/rows here.