Подтвердить что ты не робот

Можно использовать существующий ViewController с PerformSegueWithIdentifier?

Я использую метод performSegueWithIdentifier:sender:, чтобы программно открыть новый ViewController из файла раскадровки. Это работает как шарм.

Но при каждом вызове этого метода будет создан новый ViewController. Можно ли использовать существующий ViewController, если он существует? Я ничего не знаю об этой проблеме (apple-doc, Stack Overflow,...).

Проблема заключается в следующем: На созданном ViewController пользователь установил некоторые формы-Элементы, и если ViewController будет вызываться снова, элементы формы имеют начальные настройки: (

Любая помощь будет оценена.

Изменить: Я ценю многие ответы. Между тем, я не знаком с проектом и не могу проверить ваши ответы.

4b9b3361

Ответ 1

Используйте toPerforSegueWithIdentifier, чтобы либо разрешить выполнение segue, либо отменить segue и вручную добавить ViewController. Сохраните указатель в файле prepareForSegue.

... header

@property (strong, nonatomic) MyViewController *myVC;

... реализация

-(BOOL) shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender{
    if([identifier isEqualToString:@"MySegueIdentifier"]){
        if(self.myVC){
            // push on the viewController
            [self.navigationController pushViewController:self.myVC animated:YES];
             // cancel segue
            return NO; 
        }
    }
    // allow the segue to perform
    return YES;
}


-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if([segue.identifier isEqualToString:@"MySegueIdentifier"]){
        // this will only be called the first time the segue fires for this identifier
        // retian a pointer to the view controller
        self.myVC = segue.destinationViewController;
    }
}

Ответ 2

Чтобы повторно использовать существующий экземпляр UIViewController с помощью segue, создайте segue с нуля и укажите свое собственное (существующее) место назначения (UIViewController). Не забудьте вызвать prepareForSegue:, если необходимо.

Например:

UIStoryboardSegue* aSegue = [[UIStoryboardSegue alloc] initWithIdentifier:@"yourSegueIdentifier" source:self destination:self.existingViewController]
[self prepareForSegue:aSegue sender:self];
[aSegue perform];

Ответ 3

Следующий код делает singleton view controller. Добавьте их в реализацию контроллера точки назначения, затем segue повторно использует тот же vc.

static id s_singleton = nil;
+ (id) alloc {
    if(s_singleton != nil)
        return s_singleton;
    return [super alloc];
}
- (id) initWithCoder:(NSCoder *)aDecoder {
    if(s_singleton != nil)
        return s_singleton;
    self = [super initWithCoder:aDecoder];
    if(self) {
        s_singleton = self;
    }
    return self;
}

Ответ 4

Создайте свойство для контроллера.

@property (nonatomic, weak) MyController controller;

И используйте некоторую ленивую инициализацию в performSegueWithIdentifier:sender

if (self.controller == nil)
{
self.controller = [MyController alloc] init]
...
}

В этом случае, если контроллер уже создан, он будет повторно использован.

Ответ 5

Сегодня я столкнулся с этой проблемой, и то, что я сделал, - это создать контроллер представления вручную и сохранить его ссылку. Затем каждый раз, когда мне нужен контроллер, сначала проверяйте, есть ли. Что-то вроде этого:

MyController *controller = [storedControllers valueForKey:@"controllerName"];

if (!controller)
{
    controller = [[UIStoryboard storyboardWithName:@"MainStoryboard_iPhone" bundle:NULL] instantiateViewControllerWithIdentifier:@"MyControllerIdentifierOnTheStoryboard"];

    [storedControllers setValue:controller forKey:@"controllerName"];
}

[self.navigationController pushViewController:controller animated:YES];

Надеюсь, что это поможет.

Ответ 6

Если это стандартное универсальное приложение master-detail (которое использует UISplitViewController), то это может быть достигнуто путем установки свойства viewControllers на новом навигационном контроллере с предыдущим подробным контроллером, как показано ниже. В противном случае это может быть сделано, но требуется дополнительный шаг, чтобы перевести контроллер, который вы хотите повторно использовать внутри навигационного контроллера, в доске объявлений.

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([[segue identifier] isEqualToString:@"showDetail"]) {
        NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
        NSManagedObject *object = [[self fetchedResultsController] objectAtIndexPath:indexPath];
        UINavigationController* navigationController = (UINavigationController*)[segue destinationViewController];

        // retrieve previous detail controller.
        DetailViewController* controller = self.detailViewController;

        if(controller){
            // if we have an existing detail controller then set it on the navigation controller.
            navigationController.viewControllers = @[controller];
        }
        else{
            // this must be the first time, so store the detail view controller for next time, and we don't need to modify the navigation controller in this case.
            controller = (DetailViewController *)[navigationController topViewController];
            self.detailViewController = controller;
        }

        // update the detail controller as normal.
        [controller setDetailItem:object];
        controller.navigationItem.leftBarButtonItem = self.splitViewController.displayModeButtonItem;
        controller.navigationItem.leftItemsSupplementBackButton = YES;
    }
}

Есть накладные расходы на то, что каждый раз есть контроллер данных, unarchived из раскадровки, и, к сожалению, его представление также загружается. Однако он сразу же отменяется, а в шаблоне Яблоков поведение по умолчанию - это контроллер детали, загружается и отбрасывается, поэтому, если они не беспокоятся об этом, то, вероятно, безопасно это сделать.

Ответ 7

Вам нужно будет сделать Viewcontroller в одноэлементном классе.