UINavigationController 스택에서 하나의 뷰를 제거하고 다른 뷰로 교체해야하는 응용 프로그램이 있습니다. 상황은 첫 번째보기가 편집 가능한 항목을 만든 다음 항목에 대한 편집기로 자신을 대체하는 것입니다. 첫 번째보기 내에서 명백한 해결책을 수행 할 때 :
MyEditViewController *mevc = [[MYEditViewController alloc] initWithGizmo: gizmo];
[self retain];
[self.navigationController popViewControllerAnimated: NO];
[self.navigationController pushViewController: mevc animated: YES];
[self release];
나는 매우 이상한 행동을한다. 일반적으로 편집기보기가 나타나지만 탐색 모음에서 뒤로 버튼을 사용하려고하면 추가 화면이 표시되고 일부는 비어 있으며 일부는 망가졌습니다. 제목도 무작위가됩니다. 내비 스택이 완전히 튀어 나온 것과 같습니다.
이 문제에 대한 더 나은 접근 방법은 무엇입니까?
고마워, 맷
답변
나는 당신이 viewControllers
재산을 전혀 손으로 엉망으로 만들 필요가 없다는 것을 발견 했습니다. 기본적으로 이것에 대해 두 가지 까다로운 점이 있습니다.
self.navigationController
현재 탐색 컨트롤러의 스택에없는nil
경우 반환 됩니다self
. 따라서 액세스 권한을 잃기 전에 로컬 변수에 저장하십시오.- 당신은
retain
(그리고 적절하게release
)self
당신이 속한 메소드를 소유 한 객체가 할당 해제되어 이상한 일을 일으킬 것입니다.
일단 준비를 마치면 평소대로 튀어 나와서 누르십시오. 이 코드는 상단 컨트롤러를 다른 컨트롤러로 즉시 대체합니다.
// locally store the navigation controller since
// self.navigationController will be nil once we are popped
UINavigationController *navController = self.navigationController;
// retain ourselves so that the controller will still exist once it's popped off
[[self retain] autorelease];
// Pop this controller and replace with another
[navController popViewControllerAnimated:NO];
[navController pushViewController:someViewController animated:NO];
그 마지막 줄에서 당신은 변경하는 경우 animated
에 YES
다음 새 화면이 실제로 애니메이션에서 방금 튀어 컨트롤러가 밖으로 애니메이션 것입니다 것입니다. 꽤 좋아 보인다!
답변
다음 접근 방식은 나에게 더 좋게 보이며 ARC에서도 잘 작동합니다.
UIViewController *newVC = [[UIViewController alloc] init];
// Replace the current view controller
NSMutableArray *viewControllers = [NSMutableArray arrayWithArray:[[self navigationController] viewControllers]];
[viewControllers removeLastObject];
[viewControllers addObject:newVC];
[[self navigationController] setViewControllers:viewControllers animated:YES];
답변
경험상 UINavigationController의 viewControllers
속성을 직접 조작해야 할 것입니다. 다음과 같이 작동합니다.
MyEditViewController *mevc = [[MYEditViewController alloc] initWithGizmo: gizmo];
[[self retain] autorelease];
NSMutableArray *controllers = [[self.navigationController.viewControllers mutableCopy] autorelease];
[controllers removeLastObject];
self.navigationController.viewControllers = controllers;
[self.navigationController pushViewController:mevc animated: YES];
참고 : 일반적으로 더 강력하기 때문에 유지 / 릴리스를 유지 / 자동 릴리스로 변경했습니다. 유지 / 릴리스간에 예외가 발생하면 자체적으로 누출되지만 자동 릴리스가 처리합니다.
답변
많은 노력 (그리고 Kevin의 코드 수정) 끝에 마침내 스택에서 튀어 나오는 뷰 컨트롤러에서이를 수행하는 방법을 알아 냈습니다. 내가 가진 문제는 컨트롤러 배열에서 마지막 개체를 제거한 후 self.navigationController가 nil을 반환한다는 것입니다. 인스턴스 메서드 navigationController의 UIViewController에 대한 설명서에서이 줄이 원인이라고 생각합니다. “뷰 컨트롤러가 스택에있는 경우에만 탐색 컨트롤러를 반환합니다.”
현재 뷰 컨트롤러가 스택에서 제거되면 navigationController 메서드가 nil을 반환한다고 생각합니다.
작동하는 조정 된 코드는 다음과 같습니다.
UINavigationController *navController = self.navigationController;
MyEditViewController *mevc = [[MYEditViewController alloc] initWithGizmo: gizmo];
NSMutableArray *controllers = [[self.navigationController.viewControllers mutableCopy] autorelease];
[controllers removeLastObject];
navController.viewControllers = controllers;
[navController pushViewController:mevc animated: YES];
답변
고마워요, 이것이 제가 필요했던 것입니다. 나는 또한 이것을 애니메이션에 넣어 페이지 컬을 얻습니다.
MyEditViewController *mevc = [[MYEditViewController alloc] initWithGizmo: gizmo];
UINavigationController *navController = self.navigationController;
[[self retain] autorelease];
[UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration: 0.7];
[UIView setAnimationTransition:<#UIViewAnimationTransitionCurlDown#> forView:navController.view cache:NO];
[navController popViewControllerAnimated:NO];
[navController pushViewController:mevc animated:NO];
[UIView commitAnimations];
0.6 기간은 빠르며 3GS 이상에 적합하며 0.8은 여전히 3G에 비해 너무 빠릅니다 ..
요한
답변
popToRootViewController로 다른 뷰 컨트롤러를 표시하려면 다음을 수행해야합니다.
UIViewController *newVC = [[WelcomeScreenVC alloc] initWithNibName:@"WelcomeScreenVC" bundle:[NSBundle mainBundle]];
NSMutableArray *viewControllers = [NSMutableArray arrayWithArray:[[self navigationController] viewControllers]];
[viewControllers removeAllObjects];
[viewControllers addObject:newVC];
[[self navigationController] setViewControllers:viewControllers animated:NO];
이제 모든 이전 스택이 제거되고 필요한 rootViewController로 새 스택이 생성됩니다.
답변
나는 최근에 비슷한 일을해야했고 Michaels 대답에 내 솔루션을 기반으로했습니다. 제 경우에는 탐색 스택에서 두 개의 뷰 컨트롤러를 제거한 다음 새 뷰 컨트롤러를 추가해야했습니다. 부름
[컨트롤러 removeLastObject];
두 번, 제 경우에는 잘 작동했습니다.
UINavigationController *navController = self.navigationController;
// retain ourselves so that the controller will still exist once it's popped off
[[self retain] autorelease];
searchViewController = [[SearchViewController alloc] init];
NSMutableArray *controllers = [[self.navigationController.viewControllers mutableCopy] autorelease];
[controllers removeLastObject];
// In my case I want to go up two, then push one..
[controllers removeLastObject];
navController.viewControllers = controllers;
NSLog(@"controllers: %@",controllers);
controllers = nil;
[navController pushViewController:searchViewController animated: NO];
