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的主要内容,如果未能解决你的问题,请参考以下文章

如何在没有导航栏的 View Controller 内使用 Nav 推送 UIViewController

将数据从 Table View Cell 传递到 IOS 中的 View Controller

iOS中的MVC和MVVM

Google Sign In 调用 App Delegate 中的方法后关闭 View Controller (iOS / Swift)

同时切换 Tabs 和重置 Nav 的 View Controllers - Swift iOS

《iOS Human Interface Guidelines》——Page View Controller