【问题标题】:To Segue or to didSelectRowAtIndexPath?Segue 还是 didSelectRowAtIndexPath?
【发布时间】:2013-12-03 04:57:48
【问题描述】:

下面是我目前正在运行的代码。我有一个带有导航控制器和 tableview 控制器以及视图控制器的故事板设置。我正在尝试将我为表设置的 NSDictionary 中的名称传递给详细视图控制器。我应该使用 prepareforsegue 还是 didselectrowatindexpath 以及如何从字典中获取名称以传递它?

#import "FMInboxViewController.h"
#import "FMDetailViewController.h"

@interface FMInboxViewController ()

@end

@implementation FMInboxViewController

@synthesize keyArray;
@synthesize tableArray;
@synthesize tblDictionary;
@synthesize filteredArray;

- (void)viewDidLoad
{
    [super viewDidLoad];

    NSMutableArray *ary=[[NSMutableArray alloc]init];
    [ary addObject:@"Adam"];
    [ary addObject:@"Fred"];
    [ary addObject:@"Angel"];
    // ... many similar entries
    [ary addObject:@"James"];
    [ary addObject:@"Mukthesh"];

    self.tblDictionary =[self fillingDictionary:ary];
}

表格视图数据源

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    // Return the number of sections.
    return [keyArray count];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    NSArray *ary = [self.tblDictionary valueForKey:[keyArray objectAtIndex:section]];
    return [ary count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

    NSString *key = [keyArray objectAtIndex:[indexPath section]];
    NSArray *array = (NSArray *)[self.tblDictionary valueForKey:key];
    NSString *cellTitle = [array objectAtIndex:[indexPath row]];
    cell.textLabel.text = cellTitle;

    // Configure the cell...

    return cell;
}

-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    NSString *title = [keyArray objectAtIndex:section];
    return title;
}

//-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//    NSString *key = [keyArray objectAtIndex:[indexPath section]];
//    NSArray *array = (NSArray *)[self.tblDictionary valueForKey:key];
//    self.selectedName = [array objectAtIndex:indexPath.row];
//    NSLog(@"Selected Name in Did select: %@", self.selectedName);
//    
//    [self performSegueWithIdentifier:@"showDetail" sender:self];
//}

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([segue.identifier isEqualToString:@"showDetail"]) {
        NSIndexPath *section = [self.tableView indexPathForSelectedRow];
        NSString *key = [keyArray objectAtIndex:section];
        NSArray *array = (NSArray *)[self.tblDictionary valueForKey:key];
        NSString *cellTitle = [array objectAtIndex:[indexPath row]];
        NSLog(@"Selected Name in Did select: %@", self.selectedName);
    }
}

辅助方法

#pragma mark - Helper Methods

- (NSMutableDictionary *)fillingDictionary:(NSMutableArray *)sentArray {
    keyArray = [[NSMutableArray alloc] init];
    [keyArray removeAllObjects];
    NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
    [sentArray sortUsingSelector:@selector(compare:)];
    for ( NSString *str in sentArray) {
        NSString *charVal = [str substringToIndex:1];
        NSString *charStr = [NSString stringWithString:charVal];
        NSLog(@" charStr = %@", charStr);
        if (![keyArray containsObject:charStr]) {
            NSMutableArray *charArray = [[NSMutableArray alloc] init];
            [charArray addObject:str];
            [keyArray addObject:charStr];
            [dic setValue:charArray forKey:charStr];
        }
        else {
            NSMutableArray *prevArray = (NSMutableArray *)[dic valueForKey:charStr];
            [prevArray addObject:str];
            [dic setValue:prevArray forKeyPath:charStr];
        }
    }

    return dic;
}


@end

好的,我将该部分更改为如下所示

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSString *key = [keyArray objectAtIndex:[indexPath section]];
    NSArray *array = (NSArray *)[self.tblDictionary valueForKey:key];
    self.selectedName = [array objectAtIndex:indexPath.row];
    NSLog(@"Selected Name in Did select: %@", self.selectedName);
}

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    FMDetailViewController *dvc = (FMDetailViewController *)segue.destinationViewController;
    dvc.name = self.selectedName;
}

但是,现在当我选择行时,第一次按下时名称不会显示在详细控制器中。如果您返回并选择另一个名称,则您按下的第一个名称将显示在视图控制器中。关于为什么会发生这种情况的任何建议?

【问题讨论】:

  • prepareForSegue: 中,您可能的意思是:NSString *key = [keyArray objectAtIndex:section.row];? (index.row 而不是index
  • 我没有看到你在didSelectRowAtIndexPath 中的哪个位置调用了[self performSegueWithIdentifier:asdf sender:self];
  • 我把你的代码分成几部分,因为大部分都隐藏在滚动条后面。我还删除了一些冗余数据。您的问题应该尽可能简洁。
  • 感谢您的帮助。 @JamesWebster

标签: ios objective-c uitableview didselectrowatindexpath detailview


【解决方案1】:

你需要同时使用两者,在didSelectRowAtIndexPath你应该调用[self performSegueWithIdentifier:@"identifier" sender:self];

在同一个视图控制器中,您应该让prepareForSegue 方法从segue 中获取destinationViewController,然后在该视图控制器上设置您希望设置的任何属性。

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    self.someProperty = [self.someArray objectAtIndex:indexPath.row];
    [self performSegueWithIdentifier:@"segueID" sender:self];
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    UIViewController *vcToPushTo = segue.destinationViewController;
    vcToPushTo.propertyToSet = self.someProperty;
}

【讨论】:

  • 为什么他需要同时使用这两个?如果你已经在 prepareForSegue 中实例化了一个 ViewController,他可以在 didSelectRow 中推送它。
  • 执行转场和准备转场是两件不同的事情。
  • 我明白了,但是当你可以使用 navigationController 的 pushViewController 方法时,做一个 segue 是没有意义的(除非你想改变动画)。
  • “坦率地说,我不明白他们为什么会这样做”——为了简单起见?我一直按照@CouchDeveloper 所说的方式做。如果从单元格连接 segue,则无需实现 didSelectRowAtIndexPath 或调用 performSegueWithIdentifier。在 prepareForSegue 中,您使用 sender 参数(将是单元格)来获取所选单元格的 indexPath,以便将数据传递给目标视图控制器。
  • 当您使用 Xib 作为单元格时,这是一个很好的方法,并且不能直接将 segue 连接到单元格。它比只做 pushViewController 更好,因为它允许您在情节提要中拥有表示,以直观地查看正在发生的事情。
【解决方案2】:

如果可能(几乎所有标准场景都是这种情况),我会使用 Interface Builder 来触发 segue。您仍然需要实现prepareForSegue: 来配置目标视图控制器。

为了在 IB 中创建一个在点击单元格或附件按钮(在单元格的最右侧)时触发详细视图的 segue,请执行以下步骤:

  1. 控制从表格视图单元拖动到目标视图控制器并释放鼠标或触控板。这将打开小的选择面板。

  2. 选择触发器的来源,“Selection segue”或“Accessory action”以及segue的类型(“push”、“modal”或“custom”)。

  3. 在 Attributes Inspector 窗格中定义 segue 的“标识符”,例如“UserShowSegue”。

这是来自 IB 中的演示故事板的图像,它说明了如何设置“用户”视图控制器中的“表格视图单元”以触发向详细视图控制器的“推送”segue:

【讨论】:

  • 这似乎是最现代的方法,并且可以使用更多的投票来击败当前选择的答案。
  • 但在这个答案中,您并不是说如何将数据从所选行传递到目标控制器
  • @sports 您可以从prepareForSegue:segue:sender: 中的sender 参数中检索数据。 sender 是启动 segue 的对象。您可以使用此参数根据您从该对象检索的数据分别根据哪个控件(或其他对象)启动 segue 来执行不同的操作。
  • 我怎样才能让发件人成为被点击的行?如果发送者从原型单元到新的 ViewController 是自动的吗?
  • @sports 如果我没有离题,sender 是实际的UITableViewCell,其中包含已添加标签的附件视图。当您拥有单元格时,有几种方法可以获取索引路径。另见stackoverflow.com/questions/13690008/…
【解决方案3】:

可能是一个老问题,但要更详细地说明它可能关注的对象:

1- 将两者都用作提到的“(@Peter-Foti)”。

2- Segue 应该从 ParentVC 链接到 DestinationVC(而不是从原型单元)。

3- 发送者应该正确设置。

4- 设置您的“@property (someProperty)”。

示例代码:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    self.someProperty = [self.someArray objectAtIndex:indexPath.row];
    [self performSegueWithIdentifier:@"segueID" sender:self.someProperty];
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
     UIViewController *vcToPushTo = segue.destinationViewController;
     vcToPushTo.propertyToSet = sender;
}

【讨论】:

    【解决方案4】:

    因为didSelectRowAtIndexPath可以替换为storyboard可视化编程,我建议将prepareForSegue中的所有逻辑都这样处理:

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        let cell = sender as! UITableViewCell
        let indexPath = tableView.indexPath(for: cell)!
        ... and then use indexPath to set up the destination
    }
    

    【讨论】:

      猜你喜欢
      • 2014-09-11
      • 1970-01-01
      • 2015-07-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多