【问题标题】:Is it possible to refresh a single UITableViewCell in a UITableView?是否可以刷新 UITableView 中的单个 UITableViewCell?
【发布时间】:2011-05-25 19:14:05
【问题描述】:

我有一个使用UITableViewCells 的自定义UITableView。 每个UITableViewCell 有 2 个按钮。单击这些按钮将更改单元格内UIImageView 中的图像。

是否可以分别刷新每个单元格以显示新图像? 任何帮助表示赞赏。

【问题讨论】:

    标签: objective-c uitableview


    【解决方案1】:

    获得单元格的 indexPath 后,您可以执行以下操作:

    [self.tableView beginUpdates];
    [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPathOfYourCell, nil] withRowAnimation:UITableViewRowAnimationNone];
    [self.tableView endUpdates]; 
    

    在 Xcode 4.6 及更高版本中:

    [self.tableView beginUpdates];
    [self.tableView reloadRowsAtIndexPaths:@[indexPathOfYourCell] withRowAnimation:UITableViewRowAnimationNone];
    [self.tableView endUpdates]; 
    

    当然,你可以设置任何你喜欢的动画效果。

    【讨论】:

    • 在这里吹毛求疵,但当然,如果您只刷新一个单元格,您可能希望改用 [NSArray arrayWithObject:]
    • 另外,在这种情况下,beginUpdatesendUpdates 是不必要的。
    • OP 没有为任何东西设置动画,因此无需调用 begin/endupdates
    • 只要方法在最后一个公共 Xcode 版本中没有说 deprecated,所有 iOS 版本都应该没问题。
    • @Supertecnoboff 是的,但在某些时候它可能会被替换或将改变它的行为。最好尽快处理弃用
    【解决方案2】:

    我试过只打电话给-[UITableView cellForRowAtIndexPath:],但这没有用。但是,例如,以下对我有用。我allocrelease NSArray 用于严格的内存管理。

    - (void)reloadRow0Section0 {
        NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
        NSArray *indexPaths = [[NSArray alloc] initWithObjects:indexPath, nil];
        [self.tableView reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
        [indexPaths release];
    }
    

    【讨论】:

    • 这里需要[indexPaths release]吗?我认为只有在你自己分配对象时才需要它。
    • 他确实分配了 indexPaths 数组。但更好的问题是为什么他认为“严格的内存管理”是必要的。 Autorelease 在这里可以很好地完成这项工作。
    【解决方案3】:

    斯威夫特:

    func updateCell(path:Int){
        let indexPath = NSIndexPath(forRow: path, inSection: 1)
    
        tableView.beginUpdates()
        tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic) //try other animations
        tableView.endUpdates()
    }
    

    【讨论】:

    • 在哪里调用这个方法?
    【解决方案4】:

    reloadRowsAtIndexPaths: 可以,但仍会强制触发 UITableViewDelegate 方法。

    我能想到的最简单的方法是:

    UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:indexPath];
    [self configureCell:cell forIndexPath:indexPath];
    

    重要在主线程上调用您的 configureCell: 实现,因为它不会在非 UI 线程上工作(与 reloadData/@987654326 相同的故事@)。有时添加以下内容可能会有所帮助:

    dispatch_async(dispatch_get_main_queue(), ^
    {
        [self configureCell:cell forIndexPath:indexPath];
    });
    

    避免在当前可见视图之外完成的工作也是值得的:

    BOOL cellIsVisible = [[self.tableView indexPathsForVisibleRows] indexOfObject:indexPath] != NSNotFound;
    if (cellIsVisible)
    {
        ....
    }
    

    【讨论】:

    • 为什么不希望委托被调用?
    • 这是最好的方法,因为它不会强制 tableview 一直滚动到顶部,而不是 reloadRowsAtIndexPaths: 或 reloadData 方法。
    • 我这样做了,结果发现电池被回收了
    【解决方案5】:

    如果您使用的是自定义 TableViewCells,则通用

    [self.tableView reloadData];    
    

    不能有效地回答这个问题除非您离开当前视图并返回。第一个答案也没有。

    要成功地重新加载您的第一个表格视图单元格不切换视图,请使用以下代码:

    //For iOS 5 and later
    - (void)reloadTopCell {
        NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
        NSArray *indexPaths = [[NSArray alloc] initWithObjects:indexPath, nil];
        [self.tableView reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
    }
    

    插入以下调用上述方法的刷新方法,以便您可以自定义重新加载仅顶部单元格(或如果您愿意,可以重新加载整个表格视图):

    - (void)refresh:(UIRefreshControl *)refreshControl {
        //call to the method which will perform the function
        [self reloadTopCell];
    
        //finish refreshing 
        [refreshControl endRefreshing];
    }
    

    现在您已经完成了排序,在您的 viewDidLoad 中添加以下内容:

    //refresh table view
    UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
    
    [refreshControl addTarget:self action:@selector(refresh:) forControlEvents:UIControlEventValueChanged];
    
    [self.tableView addSubview:refreshControl];
    

    您现在拥有一个自定义刷新表格功能,可以重新加载顶部单元格。要重新加载整个表,请添加

    [self.tableView reloadData]; 到您的新刷新方法。

    如果您希望每次切换视图时都重新加载数据,请实现该方法:

    //ensure that it reloads the table view data when switching to this view
    - (void) viewWillAppear:(BOOL)animated {
        [self.tableView reloadData];
    }
    

    【讨论】:

      【解决方案6】:

      斯威夫特 3:

      tableView.beginUpdates()
      tableView.reloadRows(at: [indexPath], with: .automatic)
      tableView.endUpdates()
      

      【讨论】:

        【解决方案7】:

        这是一个使用 Swift 5 的 UITableView 扩展:

        import UIKit
        
        extension UITableView
        {    
            func updateRow(row: Int, section: Int = 0)
            {
                let indexPath = IndexPath(row: row, section: section)
                
                self.beginUpdates()
                self.reloadRows(at: [indexPath], with: .automatic)
                self.endUpdates()
            }
            
        }
        

        打电话给

        self.tableView.updateRow(row: 1)
        

        【讨论】:

          【解决方案8】:

          只是用 iOS 6 中的新文字语法稍微更新这些答案——您可以将 Paths = @[indexPath] 用于单个对象,或 Paths = @[indexPath1, indexPath2,...] 用于多个对象。

          就我个人而言,我发现数组和字典的文字语法非常有用并且可以节省大量时间。一方面,它更容易阅读。它消除了在任何多对象列表末尾添加 nil 的需要,这一直是个人的问题。我们都有我们的风车可以倾斜,是吗? ;-)

          只是想我会把这个混在一起。希望对您有所帮助。

          【讨论】:

          • 说 Greg,请问该语法的实际示例是什么?谢谢!
          【解决方案9】:

          我需要升级单元,但我想关闭键盘。 如果我使用

          let indexPath = NSIndexPath(forRow: path, inSection: 1)
          tableView.beginUpdates()
          tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic) //try other animations
          tableView.endUpdates()
          

          键盘消失

          【讨论】:

            猜你喜欢
            • 2013-06-28
            • 1970-01-01
            • 1970-01-01
            • 2011-12-24
            • 1970-01-01
            • 2020-10-24
            • 1970-01-01
            • 2015-10-01
            • 2016-04-17
            相关资源
            最近更新 更多