从 UITableViewCell 刷新 UITableView
Posted
技术标签:
【中文标题】从 UITableViewCell 刷新 UITableView【英文标题】:Refreshing the UITableView from UITableViewCell 【发布时间】:2009-06-25 01:49:03 【问题描述】:有没有一种简单的方法可以从 UITableViewCell 中触发 [UITableView reloadData]?我正在加载要在初始表格显示后显示的远程图像,并且使用self.image = newImage
更新图像不会刷新表格。重置单元格的文本值确实会刷新表格,但这似乎很草率。
MyTableViewCell.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
【问题讨论】:
【参考方案1】:我做了你想做的事。你要找的东西是needsLayout
。也就是说(这是我的 UITableViewCell 子类上的通知观察者):
- (void)reloadImage:(NSNotification *)notification
UIImage *image = [[SSImageManager sharedImageManager] getImage:[[notification userInfo] objectForKey:@"imageUrl"];
[self setImage:image];
[self setNeedsLayout];
这将在您的图像中弹出,而无需重新加载整个表格,这会变得非常昂贵。
【讨论】:
这正是我想要的。谢谢!【参考方案2】:使用superview
属性获取对包含UITableView
的引用。然后告诉它“reloadData
”:
UITableView *parentTable = (UITableView *)self.superview;
[parentTable reloadData];
【讨论】:
@SergiusGee 您需要遍历超级视图层次结构。我相信在父 UITableView 和子 UITableViewCell 之间有一个私有的UIView
。
不要那样做。你不能只假设堆栈下的东西。【参考方案3】:
仅重新加载需要重新加载的部分/行的成本更低。在 iPhone SDK 3.0 中,有一些方法可以做到这一点。
【讨论】:
setNeedsLayout 是 2.0+:tuvix.apple.com/iphone/library/documentation/GraphicsImaging/…【参考方案4】:嗯。那么imageWasLoaded:
是一些异步图片加载代码调用的委托方法吗?实际上,设置self.image
不会更新图像似乎很奇怪。您是否尝试将自己的UIImageView
添加到单元格而不是使用图像属性?可能是一种 hack,但这样图像应该会立即更新(无需重新加载整个表格视图,这绝对是不可取的)。
更好的是:如果您使用的是 SDK 3.0,则可以使用 UITableViewCell
中的新 imageView
属性(不过我没有尝试过):
self.imageView.image = newImage;
实际上,几周前我也需要做同样的事情。但是,我的方法是继承 UIImageView
并在该类中执行所有异步图像加载/更新。我这样做的主要原因是我想要一个通用且可重用的组件,它可以在不同的表格视图单元格(或其他地方)中使用。
【讨论】:
【参考方案5】:CodeGrue 是对的。经过几天思考为什么 [subclassOjb.tableView reloadData] 不起作用后,我放弃了试图理解这一点,并选择了我知道有效且很容易实现的唯一两种方法:1-通知中心(来自 tableviewcell 你不应该使用这个)2-或使用超级视图来处理您的 tableview 属性(这非常适合 uitableviewcells)。
请注意,使用 superview 方法仅适用于您的 uitableviewcell 类,如果您有一个自定义单元格,您可能会有一个 uitableviewcell 类,其超级视图是您的 tableviewcontroller 或任何您拥有的带有 uitableview 委托 + 数据源的类。
现在,如果您需要从另一个类(数据源类)重新加载您的 tableview,让我们说一个单例或其他类;您应该在 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];
);
);
如果您在不同的视图上并且发生了一些事情,您需要在您的表视图上重新加载您的表。好吧,那时你的桌子不在屏幕上,如果没有人看到它,你没有理由重新加载你的桌子。当用户返回到您的 tableviewcontroller 视图时,只需将 [self.tableview reloadDAta] 添加到您的 viewWillAppear 方法中,它就会即时重新加载表格。
无论如何,对于 tableviewcell,只需在您的操作中使用以下内容来重新加载数据(归功于 CodeGrue)
UITableView *parentTable = (UITableView *)self.superview;
[parentTable reloadData];
**不同的主题,但对于那些现在开始的人。这将使您免于头痛 - 在创建你的表类之后,甚至在你开始处理它的委托方法之前 - 这样做:在你的 viewDidLoad 添加以下代码:
self.tableView.delegate = self;
self.tableView.dataSource = self;
【讨论】:
【参考方案6】:任何正在寻找从单元格中重新加载表格的方法并发现 CodeGrue 的答案不起作用的人,您仍然可以这样做,但您需要仔细检查。
免责声明
您应该始终为此使用委托模式,以下是可能在未来版本中再次破坏的 hack。
破解以重新加载单元格中的数据
UITableView *parentTable = (UITableView *)self.superview;
if (![parentTable isKindOfClass:[UITableView class]])
parentTable = (UITableView *) parentTable.superview;
[parentTable reloadData];
【讨论】:
【参考方案7】:尝试 [yourtableview reloadData]; 将图像设置为新图像后
【讨论】:
如果您有大量数据,那将非常昂贵。最好只更新加载图像的单元格。以上是关于从 UITableViewCell 刷新 UITableView的主要内容,如果未能解决你的问题,请参考以下文章
获取图像后从其 imageView 刷新 UITableViewCell 布局