我该如何处理视图控制器的关闭和数据的传递?应该在哪个方法中处理,viewWillAppear还是didSelectRowAtIndexPath?我已经困扰了一段时间。
使用 委托。子视图控制器定义了一个委托协议,由父视图控制器实现。在父视图控制器显示子视图控制器之前,它将自身设置为子视图控制器的委托。当用户在子视图中选择了一行或其他内容时,子视图控制器会调用其委托的方法并关闭自身。
我为您写了一个示例代码:https://github.com/vikingosegundo/StateSelection
父视图控制器是MasterViewController。
子视图控制器是StateSelectionViewController。
The StateSelectionViewController defines a protocol in it's header: StateSelectionDelegate
and has a delegate property id<StateSelectionDelegate> delegate
.
@protocol StateSelectionDelegate <NSObject>
-(void) selectedState:(NSString *)state forNation:(NSString *)nation;
@end
MasterViewController conforms to this protocol, it implements the only delegate method selectedState:forNation:
.
-(void)selectedState:(NSString *)state forNation:(NSString *)nation
{
self.statesDictionray[nation] = state;
[self.tableView reloadData];
}
During MasterViewController's prepareForSegue:
, it sets itself a delegate of the destination view controller, which happen to be 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];
}
}
Now the segue is executed and the StateSelectionViewController's tableview gets displayed.
Once the user tabs on one of the rows, StateSelectionViewController will call
[self.delegate selectedState: <theState> forNation: <theNation>];
and dismisses or pops itself. Note the switch to determine the way the controller was presented.
-(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];
}
除了我之前的回答,我想展示另一种方法,直到几分钟前我才知道:使用取消转场而不是委托。
取消转场会以某种方式撤销将我们带到视图控制器的转场。 "某种方式"意味着您实际上不需要返回到先前的控制器,而是返回到先前的一个控制器。创建取消转场时,您将其与签名的目标连接
-(IBAction)actionName:(UIStoryboardSegue *)segue
在之前的一个视图控制器中。详情请查看这里:使用Xcode Storyboarding
调用操作的连线将包含源控制器,我们的情况是详细视图控制器。现在我们可以访问我们在其上定义的属性或方法。
@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
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];
}
扩展Vikingosegundo的建议:
当您的第一个视图控制器segue到第二个视图控制器时,实现prepareForSegue方法。
给第二个视图控制器添加一个符合parentVC协议的委托属性。
在parentVC协议中定义方法,让您通知委托当前选择的表格视图单元格。
在第一个视图控制器的prepareForSegue方法中,将自己设置为第二个视图控制器的委托。
当用户在第二个视图控制器中更改单元格时,使用委托属性通知父视图控制器。
我在github上有一个示例应用程序,说明了这种精确设置。我的设置是使用父/子视图控制器和嵌入式segue,但您可以对模态呈现、导航控制器基于导航或各种其他应用程序结构使用相同的方法。
该存储库的名称完全无用,名为“test”。您可以通过https://github.com/DuncanMC/test访问它。