ios 转场还是didSelectRowAtIndexPath?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20074953/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 22:27:13  来源:igfitidea点击:

To Segue or to didSelectRowAtIndexPath?

iosobjective-cuitableviewdidselectrowatindexpathdetailview

提问by fbm351

Below is the code that I am currently running. I have a storyboard setup with a nav controller and tableview controller and a view controller. I am trying to pass the name from the NSDictionary that I have setup for the Table to the detail view controller. Should I use prepareforsegue or didselectrowatindexpath and how would I get the name out of the dictionary to pass it along?

下面是我目前正在运行的代码。我有一个带有导航控制器和 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];
}

Table View Data Source

表视图数据源

#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);
    }
}

Helper methods

辅助方法

#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

OK, I changed that section to look like this

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

-(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;
}

However now when I select row the name won't show up in the detail controller on the first press. If you go back and select another name the first name that you pressed then shows up in the view controller. Any suggestions on why this occurs?

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

回答by Peter Foti

You need to use both, in didSelectRowAtIndexPathyou should call [self performSegueWithIdentifier:@"identifier" sender:self];

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

In the same View Controller you should have the prepareForSeguemethod grab the destinationViewControllerout of the segue, and then set whatever properties on that view controller that you wish to set.

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

- (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;
}

回答by CouchDeveloper

If possible (and this is the case in almost all standard scenarios), I would use Interface Builder to trigger the segue. You still need to implement prepareForSegue:to configure the destination view controller.

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

In order to create a segue in IB which triggers a detail view when tapping on a cell or an accessory button (on the right most side of the cell) perform these steps:

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

  1. Control drag from Table View Cell to the destination view controller and release the mouse or trackpad. This opens small selection panel.

  2. Choose the source of the trigger, either "Selection segue" or "Accessory action" and the type of the segue ("push", "modal" or "custom").

  3. In the Attributes Inspector pane define the "Identifier" of the segue, e.g. "UserShowSegue".

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

  2. 选择触发器的来源,“选择转场”或“附件动作”以及转场的类型(“”、“模态”或“自定义”)。

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

Here's an image from a Demo storyboard in IB which illustrates how the "Table View Cell" in the "Users" view controller is setup to trigger a "push" segue to a detail view controller:

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

enter image description here

在此处输入图片说明

回答by iTRQ

Might be an old question, but to be more detailed for whom it may concern:

可能是一个老问题,但更详细地说明它可能与谁有关:

1- Use both as '(@Peter-Foti)' mentioned.

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

2- Segue should be linked from the ParentVC to the DestinationVC (NOT from the Prototype Cell).

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

3- Sender should be set properly.

3- 应正确设置发件人。

4- set your '@property (someProperty)'.

4- 设置你的'@property (someProperty)'。

SAMPLE CODE:

示例代码:

- (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;
}

回答by William Entriken

Because didSelectRowAtIndexPathcan be replaced with storyboard visual programming, I recommend to do all the logic in the prepareForSeguelike this:

因为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
}