View Controller Nav 中的 iOS Refresh 按钮:单击时重新加载从解析的 JSON 创建的所有 tableViewCell

Posted

技术标签:

【中文标题】View Controller Nav 中的 iOS Refresh 按钮:单击时重新加载从解析的 JSON 创建的所有 tableViewCell【英文标题】:iOS Refresh button in View Controller Nav: reloading all tableViewCells created from parsed JSON when clicked 【发布时间】:2011-12-22 18:26:18 【问题描述】:

我有一个相当重要的概念性问题,很多人都问过,但没有现成的明确答案可以通过搜索找到。

我的应用程序很简单:几行 TableViewCells 填充了来自解析的 JSON 提要的数据。单击单元格时,该单元格的信息将传递给 SecondViewController 并显示。 JSON 提要也存储到 .plist 中,如果互联网不可用,则从 .plist 填充 TableViewCells。

这一切都很好。

但是,我需要的最后一件事是我的 FirstViewController 顶部的刷新按钮来刷新 JSON 提要,以及表中的所有单元格以及来自新变量的新数据。但是,我在实现此功能时遇到了问题:

我的原始 JSON 调用和填充单元格的变量位于 ViewDidLoad 方法中。当视图加载时,这些变量被“设置”并且不会刷新。此外,我可以将 JSON 调用和变量移动到 viewWillLoad 中——每次单击单元格后都会刷新表格,然后单击“返回”到 firstViewController——这将成功更新 JSON 和单元格,但它确实会影响当返回 MainViewController 时,速度并使视图控制器“暂停”,这使得调用我的原始 JSON 并在 viewWillLoad 中设置我的变量成为一个不可行的选项。

我在 ViewDidLoad 中创建了一个重新加载按钮,该按钮链接到 IBAction 方法“刷新”:

在 ViewDidLoad 中以编程方式创建按钮:

// Reload issues button
UIBarButtonItem *button = [[UIBarButtonItem alloc]
                           initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh
                           target:self
                           action:@selector(refresh:)];
self.navigationItem.rightBarButtonItem = button;
[button release];

它链接到的操作方法:

- (IBAction)refresh:(id)sender 

    myRawJson = [[NSString alloc] initWithContentsOfURL:[NSURL  
                                  URLWithString:@"http://www.yoursite.com/json.JSON"]  
                                  encoding:NSUTF8StringEncoding 
                                  error:nil];

    SBJsonParser *parser = [[SBJsonParser alloc] init];
    NSDictionary * myParsedJson = [parser objectWithString:myRawJson error:NULL];

// New updated dictionary built from refreshed JSON
    allLetterContents = [myParsedJson objectForKey:@"nodes"];

// Log the new refreshed JSON
    NSLog(@"You clicked refresh. Your new JSON is %@", myRawJson);

    //Maybe use the notification center?? But don't know how to implement.
    //[[NSNotificationCenter defaultCenter] addObserver:self 
                                            selector:@selector(refreshView:) 
                                            name:@"refreshView" object:nil];
    //[[NSNotificationCenter defaultCenter] postNotificationName:@"refreshView" 
                                            object:nil];

    

    [self.tableView reloadRowsAtIndexPaths:[self.tableView indexPathsForVisibleRows] 
                     withRowAnimation:UITableViewRowAnimationNone];

    [myRawJson release];

在上面的代码中,您可以看到每次单击按钮时我都会重新调用 JSON,并使用新的 JSON 将消息记录到控制台。这是有效的。我什至重新构建了一个成功添加新内容的字典。

我的问题是:如何让 tableViewCells 也用这些新数据“刷新”?我可以让按钮重新加载整个视图控制器 - 所以它会再次调用 ViewDidLoad 吗?我是否需要重新考虑我的应用程序结构,或者将我的原始变量移出 viewDidLoad?

我一直在阅读 NSNotificationCenter 上的一些帖子,但由于我对 ios 开发还很陌生。

谢谢~


更新:


它仍然没有更新。这是我的完整刷新按钮代码,带有 [self.tableView reloadData];在我的 IBAction 结束时调用。

    - (IBAction)refresh:(id)sender 
        [DSBezelActivityView newActivityViewForView:        
                         self.navigationController.navigationBar.superview     
                         withLabel:@"Loading Feed..." width:160];

        myRawJson = [[NSString alloc] initWithContentsOfURL:[NSURL 
                     URLWithString:@"http://site.com/mobile.JSON"] 
                     encoding:NSUTF8StringEncoding 
                     error:nil];

        SBJsonParser *parser = [[SBJsonParser alloc] init];
        NSDictionary * myParsedJson = [parser objectWithString:myRawJson error:NULL];
        allLetterContents = [myParsedJson objectForKey:@"nodes"];

        BOOL isEmpty = ([myParsedJson count] == 0);

        if (isEmpty) 
            NSString *refreshErrorMessage = [NSString 
stringWithFormat:@"An internet or network connection is required."];
            UIAlertView *alert = [[UIAlertView alloc] 
                                 initWithTitle:@"Alert" 
                                 message: refreshErrorMessage 
                                 delegate:self 
                                 cancelButtonTitle:@"Close" 
                                 otherButtonTitles:nil];
            [alert show];
            [alert release];

            allLetterContents = [NSMutableDictionary 
                                dictionaryWithContentsOfFile:[self saveFilePath]];
            //NSLog(@"allLetterContents from file: %@", allLetterContents);

         else 

        NSLog(@"Your new allLetterContents is %@",  allLetterContents);

          // Fast enumeration through the allLetterContents NSMutableDictionary
          for (NSMutableDictionary * key in allLetterContents) 
            NSDictionary *node = [key objectForKey:@"node"];
            NSMutableString *contentTitle = [node objectForKey:@"title"];        
            NSMutableString *contentNid = [node objectForKey:@"nid"];
            NSMutableString *contentBody = [node objectForKey:@"body"];
            // Add each Title and Nid to specific arrays
            //[self.contentTitleArray addObject:contentTitle];
            [self.contentTitleArray addObject:[[contentTitle 
                                     stringByReplacingOccurrencesOfString:@"&" 
                                     withString:@"&"] mutableCopy]];
            [self.contentNidArray addObject:contentNid];
            [self.contentBodyArray addObject:contentBody];
          

        

        [self.tableView reloadData];

        [DSBezelActivityView removeViewAnimated:YES];
        [myRawJson release];
    

我在 cellForRowAtIndexPath 处配置单元格(更新:已发布整个方法):

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

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) 
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
        if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) 
            cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
        
    

    // Configure the cell.
    cell.textLabel.text = [self.contentTitleArray objectAtIndex: [indexPath row]];
    cell.detailTextLabel.text = [self.contentNidArray objectAtIndex: [indexPath row]];
    return cell;

在 didSelectRowAtIndexPath 上设置它:

self.detailViewController.currentNodeTitle = [contentTitleArray 
                                             objectAtIndex:indexPath.row];
self.detailViewController.currentNodeNid= [contentNidArray 
                                          objectAtIndex:indexPath.row];
self.detailViewController.currentNodeBody = [contentBodyArray 
                                            objectAtIndex:indexPath.row];

因此,当单击我的刷新按钮时,表格应该* 使用新的 json 刷新,但不会。我错过了一步吗?

此外,这可能并不重要,但我正在更改每隔一行的颜色:

// Customize the appearance of table view cells.
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath 
    if (indexPath.row % 2)
    
        [cell setBackgroundColor:[UIColor colorWithRed:221.0/255.0 green:238.0/255.0 blue:255.0/255.0 alpha:1]];
        cell.textLabel.textColor = [UIColor colorWithRed:2.0/255.0 green:41.0/255.0 blue:117.0/255.0 alpha:1];
        cell.detailTextLabel.textColor = [UIColor colorWithRed:2.0/255.0 green:41.0/255.0 blue:117.0/255.0 alpha:1];

        else [cell setBackgroundColor:[UIColor clearColor]];

更新

【问题讨论】:

我怀疑cellForRowAtIndexPath: 有问题,您只粘贴了一小部分。 @Krizz - 我添加了整个 cellForRowAtIndexPath。我没有发布整个方法,因为除了我添加的内容之外,它是完全标准的。 - 谢谢 您是否使用调试器验证了[self.tableView reloadData]; 已到达并且tableView 不为零? 目前我的视图中有包含内容的单元格,所以我认为这意味着 tableView 有单元格,因此不为空。下面记录大于 0 的 NSLog: if (self.tableView > 0) [self.tableView reloadData]; NSLog(@"你的tableview大于0"); - 所以是的,我认为它不是零。我注意到的另一件事是,即使我的 IBAction 使用代码连接到刷新方法,该方法旁边的圆圈仍然显示为未链接。这一定是在您使用代码而不是 GUI 创建按钮时引起的。 (附截图)。 【参考方案1】:

你需要调用reload方法。

[self.tableView reloadData];

这将触发dataSourcedelegate 事件并刷新UITableView

您可以在UITableView Class Reference找到更多信息:

调用此方法可重新加载用于构建表格的所有数据,包括单元格、节页眉和页脚、索引数组等。为了提高效率,表格视图只重新显示那些可见的行。

【讨论】:

嗯,这是许多其他帖子所说的,但是当我添加 [self.tableView reloadData];到 - (IBAction)refresh:(id)sender 的末尾,它没有任何效果。还有其他想法吗?或者我只是在错误的地方调用它? 我已更新我的帖子以包含我的 IBAction 代码和更多信息。也许我错过了一些代码?我可以通过运行应用程序验证 JSON 是否已更改,然后更新 JSON 源,当我单击“刷新”按钮时,我的 NSLog 显示刷新按钮输出新内容,但单元格不更新。

以上是关于View Controller Nav 中的 iOS Refresh 按钮:单击时重新加载从解析的 JSON 创建的所有 tableViewCell的主要内容,如果未能解决你的问题,请参考以下文章