【问题标题】:UITableViewController: Data Parses but `numberOfRowsInSection:` returns NULL.UITableViewController:数据解析但 `numberOfRowsInSection:` 返回 NULL。
【发布时间】:2011-09-26 08:58:42
【问题描述】:

我有一个由 xml 解析的数据填充的 UITableView。解析有效,但表格保持空白。

控制台显示 xml 形式的 url 被解析并显示其组件。它还显示了当在不同的函数中询问时 tableview 的行应该具有的对象数,但 numberOfRowsInSection: 返回 Null。因此,Simulator 中的 tableView 保持空白。

这是我的代码。这是教程中的简单代码:

+++++++++++++++++ RootViewController.h++++++++++++++++++++++

#import < UIKit/UIKit.h >

@interface RootViewController : UITableViewController < NSXMLParserDelegate >{

    IBOutlet UITableView *newsTable;
    UIActivityIndicatorView *activityIndicator;
    CGSize cellSize;
    NSXMLParser *rssParser;
    NSMutableArray *stories;
    NSMutableDictionary *item;
    NSString *currentElement;
    NSMutableString *currentTitle, *currentDate, *currentSummary, *currentLink; 
}

@property (nonatomic, retain) NSMutableArray *stories;

@property (nonatomic, retain) IBOutlet UITableView *newsTable;

-(void)parseXMLFileAtURL:(NSString *)URL;

@end


+++++++++++++++++++++++++++ RootViewController.m ++++++++++++++++++++++++++++++++++++++

#import "RootViewController.h"


@implementation RootViewController
@synthesize newsTable, stories;


-(void)viewDidLoad {

    [super viewDidLoad];

    // Uncomment the following line to display an Edit button in the navigation bar for this view controller.

    // self.navigationItem.rightBarButtonItem = self.editButtonItem;
}


-(void)viewWillAppear:(BOOL)animated {

    [super viewWillAppear:animated];

    [newsTable reloadData];
}


-(void)viewDidAppear:(BOOL)animated {

    [super viewDidAppear:animated];

    if([stories count] == 0){
        NSString *path = @"http://feeds.feedburner.com/TheAppleBlog";

        [self parseXMLFileAtURL:path];      
    }

    cellSize = CGSizeMake([newsTable bounds].size.width, 60);

}

// Customize the number of sections in the table view.

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {

    return 1;
}


-(void)parseXMLFileAtURL:(NSString *)URL {

    stories = [[NSMutableArray alloc] init];

    NSURL *xmlURL = [NSURL URLWithString:URL];

    rssParser = [[NSXMLParser alloc] initWithContentsOfURL:xmlURL];

    [rssParser setDelegate:self];

    [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 the website (error code %i)", [parseError code]];

    NSLog(@"error parsing XML: %@", errorString);

    UIAlertView *errorAlert = [[UIAlertView alloc]:@"Error loading content" message:errorString delegate:self cancelButtonTitle:@"OK" otherButtonTitle: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:@"item"]) {

        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(@"End this Element %@", elementName);

    if ([elementName isEqualToString:@"item"]) {

        [item setObject:currentTitle forKey:@"title"];
        [item setObject:currentLink forKey:@"link"];
        [item setObject:currentSummary forKey:@"summary"];
        [item setObject:currentDate forKey:@"date"];

        [stories addObject:[item copy]];
        NSLog(@"adding Story : %@",currentTitle);
    }

}

// Customize the number of rows in the table view.

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    NSLog(@"Count  is = %@", [stories count]);

    return [stories count];
}


-(void)parser:(NSXMLParser *)parser  foundCharacters:(NSString *)string{

    NSLog(@"Found characters: %@", string);

    if([currentElement isEqualToString:@"title"]){

        [currentTitle appendString:string];
        NSLog(@"The Title is : %@", currentTitle);
    }   
    else if([currentElement isEqualToString:@"link"]){
        [currentLink appendString:string];
        NSLog(@"The Link is : %@", currentLink);
    }
    else if([currentElement isEqualToString:@"description"]){
        [currentSummary appendString:string];
        NSLog(@"The summary is : %@", currentSummary);
    }
    else if([currentElement isEqualToString:@"pubDate"]){
        [currentDate appendString:string];
        NSLog(@"The Date is : %@", currentDate);
    }

}

-(void)parserDidEndDocument:(NSXMLParser *)parser{

    [activityIndicator stopAnimating];

    [activityIndicator removeFromSuperview];

    NSLog(@"Stories array has %d items", [stories count]);

    NSLog(@"Stories are : %@",stories);
}


// Customize the appearance of table view cells.

-(UITableViewCell *)tableView:(UITableView *)tableView  cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *MyIdentifier = @"MyIdentifier";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];

    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:MyIdentifier] autorelease];
    }

    // Configure the cell.

    cell.textLabel.text = (NSString *)[[stories objectAtIndex:indexPath.row] objectForKey:@"title"];

    return cell;
}

-(void)dealloc {

     [super dealloc];

    [newsTable release];
    [currentDate release];
    [currentElement release];
    [currentSummary release];
    [currentLink release];
    [stories release];
    [item release];
    [currentTitle release];
    [rssParser release];
}

【问题讨论】:

  • @TechZen - 您的编辑非常出色,感谢您抽出时间在今天和其他几篇文章中帮助其他人。
  • @Tim Post -- 没什么大不了的,我现在正躺着,所以我在打发时间,因为我无法完成任何真正的工作。

标签: ios4 uitableview nsxmlparser


【解决方案1】:

扩展@omz's correct answer:

numberOfRowsInSection 方法不返回 NULL,而是返回零。 (在 Objective-C 中,nil==zero 并且 Null 是一个单例对象。)

它返回零的唯一原因是[stories count] 返回零,而[stories count] 返回零的唯一原因是它没有元素。由于您已确认解析有效并且stories 具有元素,因此 tableview 必须在解析发生之前寻找数据。

首先调用此方法,它是您重新加载数据的唯一地方:

-(void)viewWillAppear:(BOOL)animated {

    [super viewWillAppear:animated];

    [newsTable reloadData]; 
    // You trigger the tableview to call numberOfRowsInSection before stories is populated.
}

此方法仅在 tableview 出现在屏幕上后调用,并且只有在 tableview 出现后才填充stories

-(void)viewDidAppear:(BOOL)animated {

    [super viewDidAppear:animated];

    if([stories count] == 0){
        NSString *path = @"http://feeds.feedburner.com/TheAppleBlog";

        [self parseXMLFileAtURL:path];      
    }

    cellSize = CGSizeMake([newsTable bounds].size.width, 60);

}

但是,没有什么会触发 tableview 再次调用numberOfRowsInSection,因此 tableview 保持空白。只需将故事的填充移至viewWillAppear: 即可解决问题。

每次更改 tableview 所依赖的数据时(无论出于何种原因),您都必须调用 reloadData 否则 tableview 仍然不知道它不再显示当前数据集。

顺便说一句,在引用属性时应使用点表示法,以确保正确保留它们。您应该使用 self.stories 来引用 stories 属性。否则,它可能会随机释放,导致同样随机的崩溃。

【讨论】:

  • 非常感谢您的建议。但是你能告诉我如何将“故事人口”移动到 viewWillAppear :?
  • 我的意思是将stories相关代码移至viewDidAppear。更好的是,只需在viewDidAppear 中调用[newsTable reloadData];。这将导致 tableview 重新加载其数据并在 填充 stories 数组之后重绘自身。
【解决方案2】:

newsTable 插座是否正确连接到 IB 中的表格视图?而且,表格的dataSource 插座是否设置为您的视图控制器?

【讨论】:

  • 是的,“文件所有者”的newsTable outlet连接到IB中的tableView。表的数据源也连接到文件的所有者
【解决方案3】:

你必须通过调用reloadData告诉表格视图有新数据你已经解析了XML。

【讨论】:

  • 我在 viewWillAppear() 定义中调用了 [newsTable reloadData]
  • 顾名思义,viewDidAppear(你的数据被解析的地方)在viewWillAppear之后被调用。 viewWillAppear 中的reloadData 调用无效,因为还没有数据。
猜你喜欢
  • 2014-05-12
  • 2014-07-24
  • 2013-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-12
  • 2021-09-09
  • 1970-01-01
相关资源
最近更新 更多