在视图控制器之间传递行选择

时间:2013-09-25 17:04:33

标签: ios objective-c cocoa-touch uitableview

使用storyboard我目前有一个静态的Uitableview。当用户从父表视图中选择一行时,将显示一个显示某些选项的新表视图。一旦用户从新表视图中选择一行,我想关闭该表并显示父视图控制器,并在单元格中显示用户选择。几乎是表单的无线电选择。

我是否处理取消视图控制器并在视图中传递数据或在索引路径中选择行?我被困在这一段时间了。

3 个答案:

答案 0 :(得分:9)

使用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];
    
    }
    

答案 1 :(得分:5)

在我的other answer旁边,我希望在几分钟之前展示另一种我不知道的方式:使用展开的segue而不是委托。

一个展开的segue会有些反转将我们带到视图控制器的segue。 “一些如何”意味着你实际上不需要返回前一个控制器,而是前一个控制器。创建展开segue时,将其与签名目标

连接
-(IBAction)actionName:(UIStoryboardSegue *)segue

在前一个视图控制器中。详情请见:Using Xcode Storyboarding
调用动作的segue将包含源控制器,在我们的例子中是详细视图控制器。我们现在可以访问我们在其上定义的属性或方法。

@interface StateSelctionViewController : UITableViewController
@property (nonatomic, strong) NSString *selectedNation;
@property (nonatomic, strong, readonly) NSString *selectedState;
@end

我将selectedState设为readonly,以便很明显无法设置,但应在选择后读取。我在类扩展中重新声明它是readwrite。

@interface StateSelctionViewController ()
@property (nonatomic, strong, readwrite) NSString *selectedState;
@end
在故事板中的

我创建了一个手动展开的segue,如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

答案 2 :(得分:1)

扩展Vikingosegundo的建议:

当您的第一个视图控制器移位到第二个视图控制器时,请实现prepareForSegue方法。

为第二个视图控制器提供一个委托属性,该属性符合parentVC协议。

在parentVC协议中定义方法,让您通知代理当前选定的表视图单元格。

在第一个视图控制器的prepareForSegue方法中,将自己设置为第二个视图控制器的委托。

当用户更改第二个视图控制器中的单元格时,请使用delegate属性通知父视图控制器。

我在github上有一个示例应用程序,说明了这个确切的设置。我的设置是使用父/子视图控制器和嵌入segue,但您可以使用相同的方法进行模态演示,基于导航控制器的导航或各种其他应用程序结构。

回购邮件的名称完全没用“test”。你可以在https://github.com/DuncanMC/test

找到它