在视图控制器之间传递行选择
Posted
技术标签:
【中文标题】在视图控制器之间传递行选择【英文标题】:Passing row selection between view controllers 【发布时间】:2013-09-25 17:04:33 【问题描述】:使用故事板我目前有一个静态的 Uitableview。当用户从父表视图中选择一行时,会显示一个新的表视图,其中显示一些选项。一旦用户从新的表格视图中选择了一行,我想关闭表格并返回父视图控制器并让用户选择显示在单元格中。几乎是表单的单选。
我是否会处理视图控制器的关闭以及视图中数据的传递会出现还是选择索引路径处的行?我被困了一段时间。
【问题讨论】:
【参考方案1】:使用delegation。子视图控制器定义了父视图控制器实现的委托协议。在父视图控制器显示子视图控制器之前,它会将自己设置为子视图控制器的委托。当用户在子视图中选择了一行或任何内容时,子视图控制器会调用其委托的方法并关闭自己。
我为你写了一个示例代码:https://github.com/vikingosegundo/StateSelection
父视图控制器是 MasterViewController。 子视图控制器是 StateSelectionViewController。
StateSelectionViewController 在其标头中定义了一个协议:StateSelectionDelegate
,并具有一个委托属性 id<StateSelectionDelegate> delegate
。
@protocol StateSelectionDelegate <NSObject>
-(void) selectedState:(NSString *)state forNation:(NSString *)nation;
@end
MasterViewController 符合这个协议,它实现了唯一的委托方法selectedState:forNation:
。
-(void)selectedState:(NSString *)state forNation:(NSString *)nation
self.statesDictionray[nation] = state;
[self.tableView reloadData];
在 MasterViewController 的prepareForSegue:
期间,它为自己设置了一个目标视图控制器的委托,它恰好是 StateSelectionViewController。
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
if ([[segue identifier] isEqualToString:@"showDetail"])
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
NSString *selectedNation =[[[self.tableView cellForRowAtIndexPath:indexPath] textLabel] text];
[[segue destinationViewController] setSelectedNation:selectedNation];
[[segue destinationViewController] setDelegate:self];
现在执行 segue 并显示 StateSelectionViewController 的 tableview。
一旦用户在其中一行上的标签,StateSelectionViewController 将调用
[self.delegate selectedState: <theState> forNation: <theNation>];
并自行关闭或弹出。请注意用于确定控制器呈现方式的开关。
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
[self.delegate selectedState:stateDictionary[_selectedNation][indexPath.row] forNation:_selectedNation];
if(self.presentingViewController)
[self dismissViewControllerAnimated:NO completion:NULL];
else
[self.navigationController popViewControllerAnimated:YES];
【讨论】:
【参考方案2】:在我的other answer 旁边,我想展示另一种直到几分钟前我才意识到的方式:使用展开的转场而不是委托。
展开的转场将如何逆转将我们带到视图控制器的转场。 “Some how” 意味着您实际上不需要返回上一个控制器,而是返回上一个控制器。在创建展开转场时,您将其与签名的目标连接
-(IBAction)actionName:(UIStoryboardSegue *)segue
在以前的视图控制器之一中。详情请看这里:Using Xcode Storyboarding 调用动作的 segue 将包含源控制器,在我们的例子中是详细视图控制器。我们现在可以访问我们在其上定义的属性或方法。
@interface StateSelctionViewController : UITableViewController
@property (nonatomic, strong) NSString *selectedNation;
@property (nonatomic, strong, readonly) NSString *selectedState;
@end
我将 selectedState 设为只读,因此很明显不能设置,但应在选择后读取。我在类扩展中重新声明它为读写。
@interface StateSelctionViewController ()
@property (nonatomic, strong, readwrite) NSString *selectedState;
@end
在故事板中,我创建了一个手动展开的转场,如Technical Note TN2298: Figure 2所示
一旦选择了一行,我将设置selectedState
并执行展开segue
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
self.selectedState = stateDictionary[_selectedNation][indexPath.row];
[self performSegueWithIdentifier:@"unwind" sender:self];
这将在主视图控制器中执行挂钩的操作
-(void)returned:(UIStoryboardSegue *)sender
NSLog(@"%@", NSStringFromSelector(_cmd));
[self.statesDictionray setObject:[sender.sourceViewController selectedState]
forKey:[sender.sourceViewController selectedNation]];
[self.tableView reloadData];
我创建了一个示例代码:https://github.com/vikingosegundo/StateSelectionUnwind
【讨论】:
谢谢,他们都为我工作。我看到您正在使用字典来存储状态。如果我在状态视图控制器中添加一个搜索栏,我应该能够搜索可用的选项吧? 你现在用的是什么版本:委托还是这个? 我正在使用委托@vikingosegundo @EricOboite:查看新版本的委托示例。它包含一个基本过滤。 感谢工作!你能看看我最近的帖子***.com/q/19042726/1568886。我应该为此子类 UiTableViewCell 吗? @vikingosegundo【参考方案3】:扩展 Vikingosegundo 的建议:
当您的第一个视图控制器与您的第二个视图控制器分离时,请实现 prepareForSegue 方法。
为您的第二个视图控制器提供一个委托属性,该属性符合 parentVC 协议。
在您的 parentVC 协议中定义方法,让您通知代理当前选择的表格视图单元格。
在您的第一个视图控制器的 prepareForSegue 方法中,将您自己设置为第二个视图控制器的委托。
当用户更改第二个视图控制器中的单元格时,使用委托属性通知父视图控制器。
我在 github 上有一个示例应用程序,它说明了这个确切的设置。我的设置是使用父/子视图控制器并嵌入 segue,但您可以使用相同的方法进行模态表示、基于导航控制器的导航或各种其他应用程序结构。
repo 有一个完全没用的名字“test”。您可以通过https://github.com/DuncanMC/test获得它
【讨论】:
谢谢!真的很感激以上是关于在视图控制器之间传递行选择的主要内容,如果未能解决你的问题,请参考以下文章