从UITableViewCell刷新UITableView

9
有没有一种简单的方法可以在UITableViewCell内部触发[UITableView reloadData]?我正在加载远程图像,以在初始表格显示后显示,并使用self.image = newImage更新图像不会刷新表格。重置单元格的文本值可以刷新表格,但这似乎很笨拙。
我的TableViewCell.h
@interface MyTableViewCell : UITableViewCell {}
- (void)imageWasLoaded:(ImageData *) newImage;

MyTableViewCell.m

@implementation MyTableViewCell
- (void)imageWasLoaded:(UIImage *) newImageData {
    self.image = newImage; //does not refresh table

    //would like to call [self.tableView reloadData] here,
    //but self.tableView does not exist.

    //instead I use the below line
    self.text = self.text; //does refresh table
}
@end
7个回答

18

我做过你现在正在尝试做的事情。你要找的是needsLayout。比如(这是我UITableViewCell子类上的通知观察者):

- (void)reloadImage:(NSNotification *)notification
{
    UIImage *image = [[SSImageManager sharedImageManager] getImage:[[notification userInfo] objectForKey:@"imageUrl"];
    [self setImage:image];
    [self setNeedsLayout];
}
这将弹出您的图像,而无需重新加载整个表格,这可能非常昂贵。

5

使用superview属性获取包含UITableView的引用,然后告诉它"reloadData":

UITableView *parentTable = (UITableView *)self.superview;
[parentTable reloadData];

@SergiusGee 你需要遍历 superview 层级结构。我相信在父 UITableView 和子 UITableViewCell 之间有一个私有的 UIView - ninjaneer
1
不要这样做。你不能仅仅从堆栈下面假设东西。 - Gil Sand

0

嗯。所以imageWasLoaded:是一些异步图像加载代码调用的委托方法?实际上,设置self.image不会更新图像似乎有点奇怪。您是否尝试过向单元格添加自己的UIImageView而不是使用图片属性?可能有点取巧,但这样图片应该会立即更新(而无需重新加载整个表视图,这绝对不是想要的)。

更好的做法:如果您正在使用SDK 3.0,则可以在UITableViewCell中使用新的imageView属性(虽然我没有尝试过):

self.imageView.image = newImage;

其实,几周前我也需要做完全相同的事情。不过,我的方法是子类化UIImageView并在该类中执行所有异步图像加载/更新操作。我这样做的主要原因是我想要一个通用且可重复使用的组件,可以在不同的表视图单元格(或其他地方)中使用。

0

CodeGrue是正确的。在经过数天思考[subclassOjb.tableView reloadData]为什么不起作用后,我放弃了尝试理解它,并采用了我知道的唯一两种方法,这两种方法非常容易实现:1-通知中心(从tableviewcell您不应该使用此方法)2-或使用superview获取您的tableview属性的句柄(这对uitableviewcells非常完美)。

请注意,使用superview方法仅适用于您的uitableviewcell类,如果您有自定义单元格,则很有可能您将具有uitableviewcell类,其中superview是您的tableviewcontroller或任何带有uitableview委托+数据源的whateverClass。

现在,如果您需要从另一个类重新加载表视图,例如数据源类,比如单例或其他类,则应在您的tableview类中使用块在不同线程上加载数据,并使用内部块在主线程上重新加载表格。

//handle tablview to show spinner (you have to lower your tableview out of the way yourself if you are calling this method)
[self.tableView setContentOffset:CGPointMake(0, -rf.frame.size.height) animated:YES];

//start spinner animation here
[rf beginRefreshing];

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
                                         (unsigned long)NULL), ^(void) {
    // Load Data from data source class here
    [myDataSourceClass fetchDataMethod];

    dispatch_async(dispatch_get_main_queue(), ^{

         //Reload data and stop spinner
        [self.tableView reloadData];
        [rf endRefreshing];

        //handle tablview to hide spinner atrributed title
        [self.tableView setContentOffset:CGPointMake(0, 0) animated:YES];
    });
});

如果您在不同的视图中,发生需要重新加载表格视图的情况。那么此时您的表格不在屏幕上,如果没有人会看到它,就没有理由重新加载表格。只需在viewWillAppear方法中添加[self.tableview reloadData],当用户返回到您的tableviewcontroller视图时,它将实时重新加载表格。

无论如何,对于tableviewcell,只需在操作中使用以下代码即可reloadData(感谢CodeGrue)

UITableView *parentTable = (UITableView *)self.superview;
[parentTable reloadData];

虽然话题不同,但对于那些刚开始学习的人来说,这将避免可能出现的头痛 - 在创建表格类并在处理其委托方法之前,执行以下操作:在您的viewDidLoad中添加以下代码:

self.tableView.delegate = self;
self.tableView.dataSource = self; 

0
任何想要从单元格重新加载表格的人都会发现CodeGrue的答案不起作用,但你仍然可以这样做,但需要仔细检查。
免责声明
对于此操作,您应始终使用委托模式,以下是一种可能在将来版本中再次出现问题的方法。
重新加载单元格数据的Hack
UITableView *parentTable = (UITableView *)self.superview;
if (![parentTable isKindOfClass:[UITableView class]]) {
    parentTable = (UITableView *) parentTable.superview;
}

[parentTable reloadData];

0

只重新加载需要重新加载的部分/行比较省钱。在iPhone SDK 3.0中,有一些可以做到这一点的方法。


setNeedsLayout 是 2.0+ 版本可用的:http://tuvix.apple.com/iphone/library/documentation/GraphicsImaging/Reference/CALayer_class/Introduction/Introduction.html#//apple_ref/occ/instm/CALayer/setNeedsLayout - bbrown

-1
尝试在设置图像后使用 [yourtableview reloadData];

如果你有大量的数据,那将会非常昂贵。最好只更新加载图像的单元格。 - Sam Soffes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接