仅当我移动表格时刷新 UITableView 才有效?
Posted
技术标签:
【中文标题】仅当我移动表格时刷新 UITableView 才有效?【英文标题】:Refreshing the UITableView only works when I move the table? 【发布时间】:2013-09-09 21:07:17 【问题描述】:我有一个 UITableView,用户可以在其中单击附件。附件在模态视图中启动 UIView(使用 presentViewController
)。
当它返回时,它意味着用所需的数据更新 tableview 单元格。
目前我正在使用单例来捕获字典中的 userData;但即使我使用 NSNotification 我也有同样的问题。
我的问题是,当模式对话框被关闭时,tableview 永远不会更新;然而 如果我滚动或以其他方式物理移动,则表格单元格中的条目会更新。
如果我尝试使用 NSNotifications 强制重新加载单元格或整个表格视图,我会得到相同的结果。
我想知道是否可以得到一些帮助;如何使单元格重新加载?
下面是与单元格显示和模态显示方式相关的代码;
注释;
_eventName is just a NSString
-(void) viewDidAppear:(BOOL)animated
[super viewDidAppear:animated];
if ( [[MySingleton sharedInstance].userData objectForKey:@"eventName"] !=nil)
_eventName = [[MySingleton sharedInstance].userData objectForKey:@"eventName"];
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *CellIdentifier = @"Cell";
NSDictionary *dict;
NSString *name;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
dict = [_template objectAtIndex:indexPath.row];
name = [dict objectForKey:@"name"];
cell.textLabel.text = name;
NSString *key = [[dict objectForKey:@"key"] lowercaseString];
if ([[key lowercaseString] isEqualToString:@"name"]==YES)
cell.detailTextLabel.text = _eventName;
return cell;
-(void) tableView:(UITableView *)tv accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
NSDictionary *dict = [_template objectAtIndex:indexPath.row];
NSString *key = [[dict objectForKey:@"key"] lowercaseString];
NSString *name = @"";
if ([key isEqualToString:@"name"]==YES)
EventNameVC *nameEditor = [[EventNameVC alloc] initWithNibName:@"EventNameVC" bundle:nil];
if (_eventName !=nil)
nameEditor.txtName.text = _eventName;
else
nameEditor.txtName.text = name;
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:nameEditor];
// When we return from the view, reload the cell.
[self presentViewController:nav animated:YES completion:^
[self.tv reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight];
];
nav = nil;
编辑:尝试使用通知来检测模式的关闭;但我仍然有同样的问题 - 也就是说,UITableView 仅在我物理移动表格时显示更新的数据。
在我的视图控制器中我这样做;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
// Custom initialization
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
self.notificationObserver = [[NSNotificationCenter defaultCenter]
addObserverForName:@"dismissModalView"
object:nil
queue:mainQueue
usingBlock:^(NSNotification *notification)
NSLog(@"Notification received!");
NSDictionary *userInfo = notification.userInfo;
_eventName = [userInfo objectForKey:@"eventName"];
NSLog(@"received._eventName = %@", _eventName);
[self performSelectorOnMainThread:@selector(updateTable) withObject:nil waitUntilDone:YES];
];
return self;
-(void) updateTable
NSLog(@"%s", __PRETTY_FUNCTION__);
[self.tv reloadData];
我在 accessoryButtonTappedForRowWithIndexPath
方法中启动我的 modalView
EventNameVC *nameEditor = [[EventNameVC alloc] initWithNibName:@"EventNameVC" bundle:nil];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:nameEditor];
[self presentViewController:nav animated:YES completion:nil];
好的,所以当我们使用 presentViewController
启动模态视图并在关闭时,会触发通知。
在我的模态视图中
-(IBAction) btnSave:(id)sender
[self.txtName resignFirstResponder];
///[[MySingleton sharedInstance].userData setObject:self.txtName.text forKey:@"eventName"];
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:self.txtName.text forKey:@"eventName"];
[[NSNotificationCenter defaultCenter] postNotificationName:@"dismissModalView" object:self userInfo:userInfo];
[self dismissViewControllerAnimated:YES completion:nil];
当我运行它时,updateTable 会正确触发并登录到控制台。
到目前为止一切顺利。
但是tableview仍然没有刷新它的数据;我仍然需要物理移动表格才能更新单元格。
如何强制单元格正确更新?
【问题讨论】:
尝试在您的表格视图上调用reloadData
以强制刷新。
当你说把reloadData放到tableView上,用什么方法?您是指在[self presentViewController:nav animated:YES completion...
的完成块中还是其他地方?
我尝试将 reloadData 放入 viewWillAppear' like
[self.tv reloadData];` 这不会导致单元格正确显示。
愚蠢的问题:当 reloadData 被调用时,self.tv
是否指向正确的表视图?
是的。但我会尝试重写整个视图,以防我犯了一个愚蠢的错误
【参考方案1】:
问题是您在展示视图控制器(导航)时调用了– reloadRowsAtIndexPaths:withRowAnimation:
。当操作系统完成显示视图控制器时(不是当视图返回时,如您所说),“完成”块被执行,因此对用户可见。
尝试在关闭视图控制器时调用– reloadRowsAtIndexPaths:withRowAnimation:
。这可能会出现在– dismissViewControllerAnimated:completion:
的“完成”块中
希望这会有所帮助!
更新:
你好开衫;我已经看到您更新的问题,让我告诉您,如果在解雇 EventNameVC
控制器后正确调用了 updateTable
方法,则意味着问题出在其他地方。在您的表视图上调用 reloadData
将导致它使用您对基础数据源所做的任何更改来刷新其内容,除非...在您调用 reloadData
时数据源尚未更新。
通过查看您的 – tableView:cellForRowAtIndexPath:
方法,我可以看到您从这两行代码中获取了单元格的信息:
dict = [_template objectAtIndex:indexPath.row];
name = [dict objectForKey:@"name"];
信息来自_template
数组。现在,在您的模态视图中,您拥有textName
属性,我假设这是您希望最终在表格视图中显示的内容,对吧?当视图控制器被关闭时,您使用通知在字典中发送该信息,但是当您收到该通知时,我在您的块中看不到您将该信息添加到 _template
数组的任何地方。您如何更新数据源?
也请尝试以下方法:
向updateTable
方法添加断点。当应用程序停止时,添加另一个断点,但这次是在– tableView:cellForRowAtIndexPath:
方法中;这将显示reloadData
方法是否正常工作。如果应用程序随后在– tableView:cellForRowAtIndexPath:
中停止,那么您就在正确的道路上。此时继续查看数据源的内容。您可以通过直接在 XCode 控制台中键入 po _template
(然后按 Enter)来执行此操作。这样您就可以查看它是否已根据您想要的信息进行了更新。
告诉我进展如何。
【讨论】:
好的,我会试试这个。我一直在试图找出我哪里出错了,所以也许这将有助于解决它 你好。我尝试使用 NSNotification 重新加载整个表。它侦听模态解雇。通知有效;但是在我物理移动表格视图之前,表格仍然无法正确显示。您在回答中提到我可以在dismissViewControllerAnimated
中使用reloadRows...
,但我不知道该怎么做。
好的,我试试看。非常感谢,感谢您的帮助。
我已经完全重写了我的 uitableview 摆脱了所有的垃圾并使它变得简单,由于某种原因它现在可以工作了。我会接受你的回答,因为我不确定我做了什么来解决它。但它现在正在正确更新我的表格。我的表中只有 3 行,因此在这种情况下重新加载整个 tableview 并不昂贵。我将在下面发布我使用的代码。【参考方案2】:
我接受了@LuisCein 的回答。我重写了我的表格视图。正在更新中;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
// Custom initialization
self.pTemplate = [[MySingleton sharedInstance] pTemplate];
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
[[NSNotificationCenter defaultCenter]
addObserverForName:@"dismissModalView"
object:nil
queue:mainQueue
usingBlock:^(NSNotification *notification)
NSLog(@"Notification received!");
NSDictionary *userInfo = notification.userInfo;
_eventName = [userInfo objectForKey:@"eventName"];
NSLog(@"received._eventName = %@", _eventName);
[self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES];
];
return self;
...
- (NSInteger)tableView:(UITableView *)tv numberOfRowsInSection:(NSInteger)section
return pTemplate.count;
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
NSDictionary *dict = [self.pTemplate objectAtIndex:indexPath.row];
NSString *name = [dict objectForKey:@"name"];
cell.textLabel.text = name;
cell.detailTextLabel.text = @"Detail text";
NSString *key = [[dict objectForKey:@"key"] lowercaseString];
if ([[key lowercaseString] isEqualToString:@"name"]==YES)
if (_eventName !=nil) cell.detailTextLabel.text = _eventName;
if ([[key lowercaseString] isEqualToString:@"date"]==YES)
NSString *dateString = [dateFormater stringFromDate:_eventDate];
if (_eventDate !=nil) cell.detailTextLabel.text = [NSString stringWithFormat:@"%@", dateString];
if ([[key lowercaseString] isEqualToString:@"venue"]==YES)
if (_venueName != nil) cell.detailTextLabel.text = _venueName;
cell.detailTextLabel.textColor = [UIColor darkGrayColor];
return cell;
-(void) tableView:(UITableView *)tv accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
NSDictionary *dict = [self.pTemplate objectAtIndex:indexPath.row];
NSString *key = [[dict objectForKey:@"key"] lowercaseString];
if ([key isEqualToString:@"name"]==YES)
if (_eventName !=nil)
[[MySingleton sharedInstance].userData setObject:_eventName forKey:@"eventName"];
EventNameVC *nameEditor = [[EventNameVC alloc] initWithNibName:@"EventNameVC" bundle:nil];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:nameEditor];
[self presentViewController:nav animated:YES completion:nil];
nav = nil;
if ([key isEqualToString:@"date"]==YES)
if ([key isEqualToString:@"venue"]==YES)
此代码正确显示我的 uitableview 和单元格,我转到视图,更改文本并提交 nsnotification。
-(IBAction) btnSave:(id)sender
[self.txtName resignFirstResponder];
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:self.txtName.text forKey:@"eventName"];
[[NSNotificationCenter defaultCenter] postNotificationName:@"dismissModalView" object:self userInfo:userInfo];
[self dismissViewControllerAnimated:YES completion:nil];
现在似乎一切正常。 uitableview 现在正在更新,我无需滚动任何内容。
这可能只是一些愚蠢的错误,但我很高兴现在它已经解决了。
感谢大家的帮助!
【讨论】:
以上是关于仅当我移动表格时刷新 UITableView 才有效?的主要内容,如果未能解决你的问题,请参考以下文章
使用 UIRefreshControl 刷新 UITableView
UITableView 中 UISearchController 的背景颜色