UITableView prepareForSegue присваивает indexPath отправителю?
В приведенном ниже коде я просто пытаюсь настроить segue непосредственно из UIViewController
в DetailViewController
. Обычно я делаю segue из UITableViewCell
(который, я думаю, более ясен), но на этот раз я просто хотел попробовать перейти непосредственно из ViewController
, используя -tableView:didSelectRowAtIndexPath:
Мой вопрос: Я попал в ситуацию, когда мне нужно было получить доступ к UITableViewCell
indexPath
из -prepareForSegue:sender:
. Моим решением было отправить indexPath
через sender
. Обычно я задавал отправителю self
здесь, я огляделся и не могу найти ссылки на это, мне просто интересно, если использование отправителя для прохождения indexPath приемлемо? Я уверен, что это так, и я уверен, что прочитал, что вы можете где-то раньше, но теперь я не могу найти ссылку на него.
// ------------------------------------------------------------------- **
// DELEGATE: UITableView
// ------------------------------------------------------------------- **
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(@"%s", __PRETTY_FUNCTION__);
[self performSegueWithIdentifier:@"SEGUE_TWO" sender:indexPath];
}
// ------------------------------------------------------------------- **
// SEGUE: ViewController_ONE > DetailViewController
// ------------------------------------------------------------------- **
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
NSLog(@"%s", __PRETTY_FUNCTION__);
if([[segue identifier] isEqualToString:@"SEGUE_TWO"]) {
NSUInteger cellRow = [(NSIndexPath *)sender row];
DetailViewController *destinationController = [segue destinationViewController];
[destinationController setDataString:[[self dataList] objectAtIndex:cellRow]];
}
}
EDIT: Я искал в этом случае
NSIndexPath *indexPath = [[self tableView] indexPathForSelectedRow];
по существу способ получить indexPath
в -performForSegue:sender:
без необходимости передавать его через параметр отправителя (в -performSegueWithIdentifier:sender:
)
Ответы
Ответ 1
Обычно я избегаю использования отправителя в prepareForSegue:
, потому что это может быть что угодно. Это позволяет утверждать, что ваш отправитель - это то, что вы ожидаете от более громоздкого и хрупкого. Кроме того, я предпочитаю проверять класс объекта destinationViewController вместо имени segue. Ваша функциональность привязана к вашему объекту (или более определенно его интерфейсу), а не к названию вашего сеанса, поэтому проверка вашего класса дает понять, что вы пытаетесь выполнить.
Ниже приведен обычный шаблон, который я использую при производстве при переходе от UITableView
. Обратите внимание, что вы всегда должны проверить, включен ли destinationViewController в навигационном контроллере, а затем проверьте класс объекта, чтобы убедиться, что вы правильно его обрабатываете. Наконец, используйте assert, чтобы убедиться, что где-то вниз по линии вы не добавили какой-либо новый сегмент, который вы забыли обработать.
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// unwrap the controller if it embedded in the nav controller.
UIViewController *controller;
UIViewController *destVC = segue.destinationViewController;
if ([destVC isKindOfClass:[UINavigationController class]])
{
UINavigationController *navController = (UINavigationController *)destVC;
controller = [navController.viewControllers firstObject];
}
else
{
controller = destVC;
}
if ([controller isKindOfClass:[DetailViewController class]])
{
DetailViewController *vc = (DetailViewController *)controller;
NSIndexPath *ip = [self.tableView indexPathForSelectedRow];
[vc setDataString:[[self dataList] objectAtIndex:ip.row]];
}
else
{
NSAssert(NO, @"Unknown segue. All segues must be handled.");
}
}
Ответ 2
Вы можете использовать метод UITableView indexPathForCell
. Я надеюсь, что у вас есть переменная экземпляра tableView.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([sender isKindOfClass:[UITableViewCell class]]) {
NSIndexPath * indexPath = [self.tableView indexPathForCell:sender];
//Your code here
}
}