Как вернуться к корневому контроллеру, но затем нажать на другое представление?
Я пишу простое приложение, которое имеет 3 контроллера вида. Контроллер корневого представления представляет собой табличный вид item listing
. Выключив этот контроллер, я нажимаю два разных контроллера представлений на основе некоторого пользовательского взаимодействия - контроллера просмотра create item
или контроллера представления view item
.
Итак, раскадровка segues просто выглядит как V или что-то в этом роде.
В моем диспетчере представлений create item
я хотел бы, чтобы он вернулся к контроллеру корневого представления, когда пользователь создает новый элемент, но затем нажмите на контроллер view item
, чтобы я мог посмотреть на вновь созданный элемент.
Я не могу заставить это работать. Достаточно легко вернуться к контроллеру корневого представления, но я не могу нажать этот контроллер view item
.
Любые идеи? Я вставил свой код ниже. Поп-функция работает, но новый вид никогда не появляется.
- (void) onSave:(id)sender {
CLLocation *currentLocation = [[LocationHelper sharedInstance] currentLocation];
// format the thread object dictionary
NSArray* location = @[ @(currentLocation.coordinate.latitude), @(currentLocation.coordinate.longitude) ];
NSDictionary* thread = @{ @"title": _titleField.text, @"text": _textField.text, @"author": @"mustached-bear", @"location": location };
// send the new thread to the api server
[[DerpHipsterAPIClient sharedClient] postPath:@"/api/thread"
parameters:thread
success:^(AFHTTPRequestOperation *operation, id responseObject) {
// init thread object
Thread *thread = [[Thread alloc] initWithDictionary:responseObject];
// init view thread controller
ThreadViewController *viewThreadController = [[ThreadViewController alloc] init];
viewThreadController.thread = thread;
[self.navigationController popToRootViewControllerAnimated:NO];
[self.navigationController pushViewController:viewThreadController animated:YES];
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[self.navigationController popToRootViewControllerAnimated:YES];
}];
}
Ответы
Ответ 1
Легкий способ выполнить то, что вы хотите сделать, - это создать простую логику в вашем основном контроллере корневых представлений - (void) viewWillAppear и использовать обратный вызов делегата для переключения логического переключателя. в основном "обратная ссылка" на корневой контроллер. вот краткий пример.
главный корневой контроллер (рассмотрим этот контроллер a) - хорошо назовите его controllerA
установить свойство для отслеживания состояния перехода
@property (nonatomic) BOOL jumpNeeded;
установить некоторую логику в
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.jumpNeeded ? NSLog(@"jump needed") : NSLog(@"no jump needed");
if (self.jumpNeeded) {
NSLog(@"jumping");
self.jumpNeeded = NO;
[self performSegueWithIdentifier:@"controllerC" sender:self];
}
}
Теперь, в вашем основном корневом контроллере, когда выбрана строка таблицы, сделайте что-то вроде этого
при нажатии на контроллер B в вашем tableView был выбран метод
[self [email protected]"controllerB" sender:self];
затем выполните вашу подготовку к методу segue
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
//setup controller B
if([segue.identifier isEqualTo:@"controllerB"]){
ControllerB *b = segue.destinationViewController;
b.delegate = self; //note this is the back reference
}
//implement controller c here if needed
}
Теперь перейдите к контроллеру B
вам нужно установить свойство "делегат", чтобы сохранить обратную ссылку
и вам нужно импортировать файл заголовка из корневого контроллера
#import "controllerA"
@property (nonatomic,weak) controllerA *delegate;
то перед тем, как вы вернетесь к контроллеру A, вы установите флаг
self.delegate.jumpNeeded = YES;
[self.navigationController popViewControllerAnimated:YES];
и об этом. Вам не нужно ничего делать с контроллером. Есть еще несколько способов сделать это, но это довольно прямо для ваших нужд. надеюсь, что это сработает для вас.
Ответ 2
Если вы правильно поняли, у вас есть стек контроллеров:
A (root) - B - C - D - E
И вы хотите, чтобы это стало:
A (root) - F
Правильно? В этом случае:
NSArray *viewControllers = self.navigationController.viewControllers;
NSMutableArray *newViewControllers = [NSMutableArray array];
// preserve the root view controller
[newViewControllers addObject:[viewControllers objectAtIndex:0]];
// add the new view controller
[newViewControllers addObject:viewThreadController];
// animatedly change the navigation stack
[self.navigationController setViewControllers:newViewControllers animated:YES];
Ответ 3
Я думаю, что
[self.navigationController pushViewController:viewThreadController animated:YES];
использует другой NavigationController, чем выражение перед этим.
Поскольку после появления в корневом представлении Controller вы потеряете контроллер навигации, в котором находитесь. Решите, что вместо этого используйте этот код
UINavigationController *nav = self.navigationController;
[self.navigationController popToRootViewControllerAnimated:NO];
[nav pushViewController:viewThreadController animated:YES];
Я также думаю, что это не решит вашу проблему. Вероятно, вы получите сообщение о том, что два быстрых нажатия и нажатия могут привести к аннулированию функции NavigationController.
И чтобы решить это, вы можете либо нажать на NavigationController в методе viewDidDissappear 2-го контроллера просмотра, либо нажать его в методе viewDidAppear в главном контроллере просмотра (список элементов).
Ответ 4
Обмен категорией в UINavigationController на основе ответа Dave DeLong, который мы используем в нашем приложении, чтобы поддерживать обратную кнопку, всегда работая по мере необходимости.
@implementation UINavigationController (PushNewAndClearNavigationStackToParent)
- (void) pushNewControllerAndClearStackToParent:(UIViewController*)newCont animated:(BOOL)animated
{
NSArray *viewControllers = self.viewControllers;
NSMutableArray *newViewControllers = [NSMutableArray array];
// preserve the root view controller
[newViewControllers addObject:[viewControllers firstObject]];
// add the new view controller
[newViewControllers addObject:newCont];
// animatedly change the navigation stack
[self setViewControllers:newViewControllers animated:animated];
}
@end
Ответ 5
NSArray *viewControllers = self.navigationController.viewControllers;
NSMutableArray *newViewControllers = [NSMutableArray array];
// preserve the root view controller
for(int i = 0; i < [viewControllers count];i++){
if(i != [viewControllers count]-1)
[newViewControllers addObject:[viewControllers objectAtIndex:i]];
}
// add the new view controller
[newViewControllers addObject:conversationViewController];
// animatedly change the navigation stack
[self.navigationController setViewControllers:newViewControllers animated:YES];
Ответ 6
Я не думаю, что это возможно, потому что popping назад освободит все.
Я думаю, что лучший способ - поместить ваши данные в модельный одноэлементный класс, поп-серверу rootviewcontroller и послушать поп-конец. Затем вы проверяете, есть ли какие-то данные, хранящиеся на модели, чтобы вы знали, нужно ли вы нажимать новый диспетчер представлений.
Ответ 7
Я использовал Дэйв в качестве вдохновения и сделал это для Свифта:
let newViewControllers = NSMutableArray()
newViewControllers.addObject(HomeViewController())
newViewControllers.addObject(GroupViewController())
let swiftArray = NSArray(array:newViewControllers) as! Array<UIViewController>
self.navigationController?.setViewControllers(swiftArray, animated: true)
- Замените HomeViewController() тем, что вы хотите, чтобы ваш контроллер нижнего представления был
- Замените GroupViewController() тем, что вы хотите, чтобы ваш контроллер верхнего уровня был
Ответ 8
Если то, что вы хотите сделать, это каким-либо образом перемещаться внутри одного и того же навигационного контроллера... вы можете получить доступ к navigationStack A.K.A. viewControllers, а затем установите viewcontrollers в том порядке, который вы хотите, или добавьте или удалите некоторые...
Это самый чистый и естественный способ сделать это.
UINavigationController* theNav = viewControllerToDismiss.navigationController;
UIViewController* theNewController = [UIViewController new];
UIViewController* rootView = theNav.viewControllers[0];
[theNav setViewControllers:@[
rootView,
theNewController
] animated:YES];
выполните необходимые проверки, чтобы вы не получили никаких исключений.