Можно использовать существующий ViewController с PerformSegueWithIdentifier?
Я использую метод performSegueWithIdentifier:sender:
, чтобы программно открыть новый ViewController
из файла раскадровки. Это работает как шарм.
Но при каждом вызове этого метода будет создан новый ViewController
. Можно ли использовать существующий ViewController
, если он существует? Я ничего не знаю об этой проблеме (apple-doc, Stack Overflow,...).
Проблема заключается в следующем:
На созданном ViewController
пользователь установил некоторые формы-Элементы, и если ViewController
будет вызываться снова, элементы формы имеют начальные настройки: (
Любая помощь будет оценена.
Изменить:
Я ценю многие ответы. Между тем, я не знаком с проектом и не могу проверить ваши ответы.
Ответы
Ответ 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 в одноэлементном классе.