Selecting TableView cells not working correctly


#1

Hello, I’m having a strange problem withe my app. The titles seem to load into my table view cell rows correctly, but they do no always respond by bringing up the web page. If I click on the first one, nothing happens. I click on the second one, and it brings up the web page. When I go back and try to click on that same row again, nothing happens. But then I can click on the first one, and it will work. They seem to alternate like this, becoming active and inactive. This happens down through the list of rows. I added and NSLog message to identify when the rows are selected. I assume the rows should go from 0 to however many there are in the table, and stay the same. The row numbers seem to change with this strange behavior. I have checked my code multiple times, and I cannot find an issue. I’ve included my code. Any help is appreciated. Thanks.

[code]//
// NerdFeedAppDelegate.h
// NerdFeed
//
// Created by on 1/28/13.
// Copyright © 2013. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface NerdFeedAppDelegate : UIResponder

@property (strong, nonatomic) UIWindow *window;

@end[/code]

[code]//
// NerdFeedAppDelegate.m
// NerdFeed

#import “NerdFeedAppDelegate.h”
#import “ListViewController.h”
#import “WebViewController.h”

@implementation NerdFeedAppDelegate

  • (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.

    ListViewController *lvc = [[ListViewController alloc] initWithStyle:UITableViewStylePlain];
    UINavigationController *masterNav = [[UINavigationController alloc] initWithRootViewController:lvc];

    WebViewController *wvc = [[WebViewController alloc] init];
    [lvc setWebViewController:wvc];

    [[self window] setRootViewController:masterNav];

    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    return YES;
    }

  • (void)applicationWillResignActive:(UIApplication *)application
    {
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
    }

  • (void)applicationDidEnterBackground:(UIApplication *)application
    {
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    }

  • (void)applicationWillEnterForeground:(UIApplication *)application
    {
    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
    }

  • (void)applicationDidBecomeActive:(UIApplication *)application
    {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }

  • (void)applicationWillTerminate:(UIApplication *)application
    {
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    }

@end[/code]

[code]//
// ListViewController.h
// NerdFeed

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@class RSSChannel;
@class WebViewController;

@interface ListViewController : UITableViewController
<NSURLConnectionDelegate, NSXMLParserDelegate>

{
NSURLConnection *connection;
NSMutableData *xmlData;

RSSChannel *channel;

}

@property (nonatomic, strong) WebViewController *webViewController;

  • (void)fetchEntries;

@end[/code]

[code]//
// ListViewController.m
// NerdFeed

#import “ListViewController.h”
#import “RSSChannel.h”
#import “RSSItem.h”
#import “WebViewController.h”

@implementation ListViewController

@synthesize webViewController;

  • (void)parser:(NSXMLParser *)parser
    didStartElement:(NSString *)elementName
    namespaceURI:(NSString *)namespaceURI
    qualifiedName:(NSString *)qName
    attributes:(NSDictionary *)attributeDict
    {
    NSLog(@"%@ found a %@ element", self, elementName);
    if ([elementName isEqual:@“channel”]) {
    channel = [[RSSChannel alloc] init];
    [channel setParentParserDelegate:self];
    [parser setDelegate:channel];
    }
    }

  • (id)initWithStyle:(UITableViewStyle)style
    {
    self = [super initWithStyle:style];
    if (self) {
    [self fetchEntries];
    }
    return self;
    }

  • (void)fetchEntries
    {
    xmlData = [[NSMutableData alloc] init];
    NSURL *url = [NSURL URLWithString:
    @"http://forums.bignerdranch.com/smartfeed.php?"
    @“limit=1_DAY&sort_by=standard&feed_type=RSS2.0&feed_style=COMPACT”];
    NSURLRequest *req = [NSURLRequest requestWithURL:url];
    connection = [[NSURLConnection alloc] initWithRequest:req
    delegate:self
    startImmediately:YES];
    }

  • (void)connection:(NSURLConnection *)conn didReceiveData:(NSData *)data
    {
    [xmlData appendData:data];
    }

  • (void)connectionDidFinishLoading:(NSURLConnection *)conn
    {
    NSXMLParser *parser = [[NSXMLParser alloc] initWithData:xmlData];
    [parser setDelegate:self];
    [parser parse];
    xmlData = nil;
    connection = nil;
    [[self tableView] reloadData];
    NSLog(@"%@\n %@\n %@\n", channel, [channel title], [channel infoString]);
    }

  • (void)connection:(NSURLConnection *)conn didFailWithError:(NSError *)error
    {
    connection = nil;
    xmlData = nil;
    NSString *errorString = [NSString stringWithFormat:@“Fetch failed: %@”,[error localizedDescription]];

    UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"Error"
    message:errorString
    delegate:nil
    cancelButtonTitle:@"OK"
    otherButtonTitles:nil];
    [av show];
    }

  • (NSInteger)tableView:(UITableView *)tableView
    numberOfRowsInSection:(NSInteger)section
    {
    return [[channel items] count];
    }

  • (UITableViewCell *)tableView:(UITableView *)tableView
    cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@“UITableViewCell”];
    if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
    reuseIdentifier:@“UITableViewCell”];
    }
    RSSItem *item = [[channel items] objectAtIndex:[indexPath row]];
    [[cell textLabel] setText:[item title]];

    return cell;
    }

  • (void)tableView:(UITableView *)tableView
    didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
    {
    NSLog (@“Did select row %d from table”, [indexPath row]);
    [[self navigationController] pushViewController:webViewController animated:YES];
    RSSItem *entry = [[channel items] objectAtIndex:[indexPath row]];
    NSURL *url = [NSURL URLWithString:[entry link]];
    NSURLRequest *req = [NSURLRequest requestWithURL:url];
    [[webViewController webView] loadRequest:req];
    [[webViewController navigationItem] setTitle:[entry title]];
    }

@end[/code]

[code]//
// WebViewController.h
// NerdFeed

#import <Foundation/Foundation.h>

@interface WebViewController : UIViewController

@property (nonatomic, readonly) UIWebView *webView;

@end[/code]

[code]//
// WebViewController.m
// NerdFeed

#import “WebViewController.h”

@implementation WebViewController

  • (void)loadView
    {
    CGRect screenFrame = [[UIScreen mainScreen] applicationFrame];
    UIWebView *wv = [[UIWebView alloc] initWithFrame:screenFrame];
    [wv setScalesPageToFit:YES];
    [self setView:wv];
    }

  • (UIWebView *)webView
    {
    return (UIWebView *)[self view];
    }

@end[/code]

[code]//
// RSSChannel.h
// NerdFeed

#import <Foundation/Foundation.h>

@interface RSSChannel : NSObject
{
NSMutableString *currentString;
}

@property (nonatomic, weak) id parentParserDelegate;
@property (nonatomic, strong) NSString *title;
@property (nonatomic, strong) NSString *infoString;
@property (nonatomic, readonly, strong) NSMutableArray *items;

@end[/code]

[code]//
// RSSChannel.m
// NerdFeed

#import “RSSChannel.h”
#import “RSSItem.h”

@implementation RSSChannel
@synthesize items, title, infoString, parentParserDelegate;

  • (id)init
    {
    self = [super init];
    if (self) {
    items = [[NSMutableArray alloc] init];
    }
    return self;
    }

  • (void)parser:(NSXMLParser *)parser
    didStartElement:(NSString *)elementName
    namespaceURI:(NSString *)namespaceURI
    qualifiedName:(NSString *)qName
    attributes:(NSDictionary *)attributeDict
    {
    NSLog(@"\t%@ found a %@ element", self, elementName);

    if ([elementName isEqual:@“title”]) {
    currentString = [[NSMutableString alloc] init];
    [self setTitle:currentString];
    }
    else if ([elementName isEqual:@“description”]) {
    currentString = [[NSMutableString alloc] init];
    [self setInfoString:currentString];
    }
    else if ([elementName isEqual:@“item”]) {
    RSSItem *entry = [[RSSItem alloc] init];
    [entry setParentParserDelegate:self];
    [parser setDelegate:entry];
    [items addObject:entry];
    }
    }

  • (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)str
    {
    [currentString appendString:str];
    }

  • (void)parser:(NSXMLParser *)parser
    didEndElement:(NSString *)elementName
    namespaceURI:(NSString *)namespaceURI
    qualifiedName:(NSString *)qName
    {
    currentString = nil;
    if([elementName isEqual:@“channel”]) {
    [parser setDelegate:parentParserDelegate];
    }
    }

@end[/code]

[code]//
// RSSItem.h
// NerdFeed

#import <Foundation/Foundation.h>

@interface RSSItem : NSObject
{
NSMutableString *currentString;
}

@property (nonatomic, weak) id parentParserDelegate;
@property (nonatomic, strong) NSString *title;
@property (nonatomic, strong) NSString *link;

@end[/code]

[code]//
// RSSItem.m
// NerdFeed

#import “RSSItem.h”

@implementation RSSItem

@synthesize title, link, parentParserDelegate;

  • (void)parser:(NSXMLParser *)parser
    didStartElement:(NSString *)elementName
    namespaceURI:(NSString *)namespaceURI
    qualifiedName:(NSString *)qName
    attributes:(NSDictionary *)attributeDict
    {
    NSLog(@"\t%@ found a %@ element", self, elementName);

    if ([elementName isEqual:@“title”]) {
    currentString = [[NSMutableString alloc] init];
    [self setTitle:currentString];
    }
    else if ([elementName isEqual:@“link”]) {
    currentString = [[NSMutableString alloc] init];
    [self setLink:currentString];
    }
    }

  • (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)str
    {
    [currentString appendString:str];
    }

  • (void)parser:(NSXMLParser *)parser
    didEndElement:(NSString *)elementName
    namespaceURI:(NSString *)namespaceURI
    qualifiedName:(NSString *)qName
    {
    currentString = nil;
    if([elementName isEqual:@“item”]) {
    [parser setDelegate:parentParserDelegate];
    }
    }

@end[/code]


#2

Hi,

You have didDeselectRowAtIndexPath instead of didSelectRowAtIndexPath

HTH
Gareth


#3

Gareth,
Thanks for your help! I made the change and it worked. That happened to me once before. I even printed my files out to look at them more closely and I still missed it. This forum is great!


#4

I had same problem. Thanks to OP for going to all the trouble to document. And to responder for… responding!