从另一个 UIViewController 刷新表
Posted
技术标签:
【中文标题】从另一个 UIViewController 刷新表【英文标题】:Refresh table from another UIViewController 【发布时间】:2014-07-10 15:56:31 【问题描述】:我有两个视图控制器,其中一个 (ViewController
) 有一个名为 tableView
的表。
我想从我的其他视图控制器 (pageView
) 刷新此表。
我已经在pageView
:
ViewController*refresh;
[refresh.tableView reloadData];
但这不起作用。
两个视图控制器之间的连接segue是push segue
我该怎么办?我应该通过故事板segue来做吗?
【问题讨论】:
当你第一次init
你的控制器时,使用单例。然后,您可以从任何地方调用 [[Controller sharedInstance].tableView reloadData],假设 tableView 是公共属性。
pageView 发生了什么?页面视图是否检索数据并将新数据推送到用于显示 tableView 的数组?页面视图是视图吗? NSNotification 应该可以正常工作,因为我有类似的实现。除非您尝试从 pageView 触发 NSNotification 而 tableView 根本不处于活动状态。
【参考方案1】:
选项 1
@Class2
@property (nonatomic) BOOL shouldRefresh; // in .h file
- (void)viewWillAppear:(BOOL)animated // in .m file
[super viewWillAppear:animated];
if (_shouldRefresh) [self.tableView reloadData];
@Class1
// Add this in any method where you want it to refresh and push to view
ClassTwoController *viewController = [[ClassTwoController alloc] init];
[viewController setShouldRefresh:YES];
[self.navigationController pushViewController:viewController animated:YES];
*更新:
选项 2
@Class 2
// Add this line in viewDidLoad in same class you want the tableView to refresh
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refreshTableWithNotification:) name:@"RefreshTable" object:nil];
// Add this method just beneath viewDidLoad:
- (void)refreshTableWithNotification:(NSNotification *)notification
[self.tableView reloadData];
@Class1
// Call this when ever you want to refresh the tableView in Class2
[[NSNotificationCenter defaultCenter] postNotificationName:@"RefreshTable" object:nil userInfo:nil];
【讨论】:
我可以这样做而不必重新创建ClassTwoController
吗?因为我有一个不想发生两次的启动动画!
嗯,是的,你不必重新分配,如果它是一个全局变量,你可以使用以下内容:[self.viewController setShouldRefresh:YES];
不,我的意思是在不“重新创建它”的情况下,我怎么能做到 ClassTwoController *viewController = [[ClassTwoController alloc] init];
这是一种方式,另一种方式是在视图消失时删除数据,然后在视图出现时重新加载新数据。或者您可以添加NSNotificationCenter
发送通知,通知表应该由于新数据而重新加载,一旦收到通知,表将重新加载。
那你做错了,因为我知道这很有效,我也在使用它,它在这个线程中得到了最多的支持,这告诉你什么?【参考方案2】:
/* 在 ViewController 的 viewDidLoad 方法中添加这一行(通过使用这一行,您正在向 ViewController 类添加通知观察者)*/
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reloadTableview:) name:@"ReloadTableview" object:nil];
/* 在 ViewController 类中添加此方法(在 pageView 中发布通知时调用此方法) */
- (void)reloadTableview:(NSNotification *)notif
[tableView reloadData];
/* 在您想要刷新的时间/位置添加此行(在 ViewController 中添加的此行发布通知)*/
[[NSNotificationCenter defaultCenter] postNotificationName:@"ReloadTableview" object:nil];
【讨论】:
【参考方案3】:在 ViewController1 中:
> Create property for UITableview with nonatomic and retain
> Now Create table Object.
在 ViewController2.m 中:
ViewController1 *objV1 = [ViewController1 alloc]initWithNibName....];
[objV1.yourTableView reloadData];
【讨论】:
ViewController *vc = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil]; 可是桌子不是笔尖?我可以不做 innit 吗? 看这个:[***.com/questions/6188387/… 如果您分配/初始化 vc1,您将创建另一个控制器实例,因此它将无法工作。【参考方案4】:如果第二个视图控制器已经加载,那么你可以在第一个视图控制器中使用 NSNotification。此通知将调用第二个视图控制器中的方法。在此方法中编写代码以重新加载 tableview。
【讨论】:
【参考方案5】:如果我理解正确,您想重新加载导航堆栈的前一个视图控制器中存在的表视图。如果是这样,您可以通过导航控制器的viewControllers
属性访问它。
NSUInteger indexOfTableController = self.navigationController.viewControllers.count - 2;
ViewController *tableController = (ViewController*)[self.navigationController.viewControllers objectAtIndex:indexOfTableController];
[tableController.tableView reloadData];
【讨论】:
@Maximilian 你有什么错误吗?我对您的视图控制器层次结构的假设是否正确? @Maximilian 如果您重新加载ViewController
(具有表格视图的那个)viewWillAppear
上的数据,表格会更新吗?
就是ViewController
中的这个-(void)viewDidAppear
吗?
-(void)viewWillAppear:(BOOL)animated [super viewWillAppear:animated]; [self.tableView reloadData];
是的,从 push segue 回来时仍然没有任何反应。我可能会创建一个新的转场!【参考方案6】:
发生这种情况的最常见原因是您没有正确初始化对第二个控制器的引用并且它保持为零。必须是这样的。
@implementation
ViewController *refresh;
- (void) openNewController
refresh = [[ViewController alloc] init];
[self.navigationController pushViewController:refresh animated:true];
- (void) refreshNewController
[refresh.tableView reloadData];
@end
【讨论】:
这只是恢复到第一个 ViewController 然后它变黑了!【参考方案7】:好吧,举例来说,让我们调用以前的 ViewController VC1 和当前的 ViewController VC2。
所以你做了一个从 VC1 到 VC2 的 push segue。您可以做的是:在 segue 期间将 TableView 的引用传递给 VC2。因此,您将在 VC2 中创建一个公共 UITableView tblView 变量,然后在 VC1 中实现 prepareForSegue 方法
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
if ([[segue identifier] isEqualToString:@"Segue_Identifier_From_StoryBoard"])
// get your destination view controller
VC2 *vc2 = [segue destinationViewController];
vc2.tblView = TableView;
然后在 VC2 中,你可以调用 [tblView reloadData];
使用完 VC2 后,请确保将 tblView 引用设为 nil。
【讨论】:
“确保你 nil tblView”是什么意思?【参考方案8】:您可以查看 viewcontroller.tableview 和 refresh.tableView 的地址,我认为它们会不一样; 您可以为视图控制器制作单例,然后调用例如
viewcontroller *vc = [viewcontroller sharedInstance];
[[vc tableview] reloadData];
【讨论】:
我收到错误:No known class method for selector 'sharedInstance'
【参考方案9】:
在你的pageView中创建一个方法
-(void) reloadVCController
ViewController*vc=[[ViewController alloc]init]];
[vc.tableview reloadData;
并在你想调用它的地方使用它
[self reloadVCController];
【讨论】:
【参考方案10】:ViewController*refresh;
[refresh.tableView reloadData];
通过查看上述代码,您并未将您的 ViewController instance
分配给 refresh
。执行reloadData()
时,您的refresh
将为零,因此显然它不会对任何操作做出反应。
ViewController*refresh = originalInstance; //assign your original instance here
[refresh.tableView reloadData];
这会起作用,这里要注意的要点是您的刷新 viewcontroller
应该是堆栈中最顶层的实例,因为任何 UI 操作都应该发生在主线程中。
【讨论】:
【参考方案11】:使用 NSnotification 中心在该视图控制器中添加观察者并编写重新加载表的方法。 [self.tableView reloadData]; 并从当前视图帖子通知该观察者。
【讨论】:
【参考方案12】:如果您已经尝试了所有答案,请确保在重新加载 tableView 之前,dataSource 已实际更新包含新/附加/内容。
【讨论】:
【参考方案13】:Reloaddata 需要在 parentviewcontroller 中执行,因为它调用 tableview 委托方法来重新加载表格,例如 CellForRowAtIndexpath 等等。 这意味着您需要在 parentviewcontroller 中定义一个公共方法,该方法将包含 reloaddata 命令并从子视图控制器调用它。
公共方法:
父视图控制器.h
@interface
-(void) reloadTable:(id) sender;
parentviewcontroller.m
@implementation
- (void) reloadTable:(id) sender
[self.tableview reloaddata];
return;
childviewcontroller.h
#import parentviewcontroller.h
@class parentviewController
@interface childviewcontroller :UIViewController (or UITableViewController)
@property (nonatomic, strong) parentViewController *parent;
childviewController.m
@implementation
@synthesize parent;
/* Note the parent instance is passed from the parent to the child view controller,
it is not allocated and initialised in the child controller - many ways to do this
depending on coding style */
/* after updating the data */
[parent reloadTable];
【讨论】:
你应该对父级有弱引用,否则你会创建保留循环(你可以手动打破它,但为什么要这样做)。【参考方案14】:我认为问题在于您 refresh 控制器视图未加载。因此,reloadTable 消息只是归零。您可以通过调用 view getter 来强制 View Controller 加载其视图:
[viewController view];
所以检查您的 tableView 是否为 nil,如果是,请使用描述的方法对其进行初始化。
【讨论】:
【参考方案15】:作为对情感的化妆回答:
如果你想跳过启动动画,只需在 ClassTwoController
中设置一个 bool 属性来检查它是否是第一次加载此视图
ClassTwoController.h:
@property (nonatomic, assign) BOOL notFirstTimeRun;
ClassTwoController.m:
-(void)viewWillAppear:(BOOL)animated // in .m file
if(self.notFirstTimeRun)
[self.tableView reloadData];
else
[self playStartUpAnime];
-(void)playStartUpAnimation // in .m file
//Place your codes for animation here
在您的 ClassOneController
.m 中使用 check bool 对其进行初始化:
ClassTwoController *viewController = [[ClassTwoController alloc] init];
viewController.notFirstTimeRun = YES;
【讨论】:
【参考方案16】:如果你有父子关系,你可以像这样向子视图控制器添加弱属性
@property (nonatomic, weak) ParentViewController *parentController;
然后当您需要重新加载表时,您只需调用[parentController.tableView reloadData]
其他方式是使用 NSNotificationCenter。在控制器中,您要重新加载表,您应该订阅通知([[NSNotificationCenter defaultCenter] addObserver...]
)并实现您提供给此方法的选择器。在另一个控制器中,您应该使用该名称发布通知。
如果 viewWillAppear 适合您的需要,您也可以只刷新它。
【讨论】:
以上是关于从另一个 UIViewController 刷新表的主要内容,如果未能解决你的问题,请参考以下文章
从另一个 UIViewController 中呈现一个 UIViewController?
从另一个 UIViewController 呈现 UIViewController
从另一个 UIViewController 推送一个 UIViewController - 如何?
如何从另一个 UIViewController 触发 UITabBarController 的一个 UIViewController?