UINavigation Controller에서 보기를 팝업하고 한 번의 작업으로 다른 보기로 바꾸려면 어떻게 해야 합니까?
UINavigation Controller 스택에서 보기 하나를 제거하고 다른 보기로 바꿔야 하는 응용 프로그램이 있습니다.이 경우 첫 번째 보기는 편집 가능한 항목을 만든 다음 항목의 편집기로 대체됩니다.첫 번째 보기 내에서 명확한 솔루션을 수행할 때:
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];
만약 당신이 그것을 바꾼다면 그 마지막 줄에서.animatedYES그러면 새 화면이 실제로 애니메이션으로 표시되고 방금 팝업한 컨트롤러가 애니메이션으로 표시됩니다.꽤 좋아 보이네요!
다음과 같은 접근 방식이 더 좋은 것으로 보이며 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];
경험에 비추어 볼 때, 당신은 UIN 내비게이션 컨트롤러를 만지작거려야 할 것입니다.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가 0으로 반환되었다는 것입니다.인스턴스 메서드 navigationController의 UIViewController 설명서에 있는 이 행 때문인 것 같습니다. "ViewController가 스택에 있는 경우에만 탐색 컨트롤러를 반환합니다."
현재 뷰 컨트롤러가 스택에서 제거되면 navigationController 메서드가 0으로 반환될 것이라고 생각합니다.
작동하는 조정된 코드는 다음과 같습니다.
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를 사용하여 새 스택이 생성됩니다.
저는 최근에 비슷한 일을 해야 했고 마이클스의 답변을 기반으로 해결책을 마련했습니다.이 경우 탐색 스택에서 두 개의 View 컨트롤러를 제거한 다음 새 View 컨트롤러를 추가해야 했습니다.부르기
[컨트롤러가 LastObject 제거];twice, worked fine in my case.
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];
것이.UINavigationController인스턴스 메서드가 작동할 수 있습니다...
지정된 뷰 컨트롤러가 최상위 뷰 컨트롤러가 될 때까지 뷰 컨트롤러를 팝업한 다음 디스플레이를 업데이트합니다.
- (NSArray *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated
다음은 viewControllers 배열을 직접 조작할 필요가 없는 또 다른 접근 방식입니다.컨트롤러가 아직 팝업되지 않았는지 확인하고, 컨트롤러를 누릅니다.
TasksViewController *taskViewController = [[TasksViewController alloc] initWithNibName:nil bundle:nil];
if ([navigationController.viewControllers indexOfObject:taskViewController] == NSNotFound)
{
[navigationController pushViewController:taskViewController animated:animated];
}
else
{
[navigationController popToViewController:taskViewController animated:animated];
}
NSMutableArray *controllers = [self.navigationController.viewControllers mutableCopy];
for(int i=0;i<controllers.count;i++){
[controllers removeLastObject];
}
self.navigationController.viewControllers = controllers;
제가 가장 좋아하는 방법은 UI 내비게이션 컨트롤러의 범주를 사용하는 것입니다.다음이 작동해야 합니다.
UI 내비게이션 컨트롤러+helpers.h #가져오기
@interface UINavigationController (Helpers)
- (UIViewController*) replaceTopViewControllerWithViewController: (UIViewController*) controller;
@end
UI 내비게이션 컨트롤러+도우미
"UINavigationController+"UINavigationController+"도우미들.h"
@implementation UINavigationController (Helpers)
- (UIViewController*) replaceTopViewControllerWithViewController: (UIViewController*) controller {
UIViewController* topController = self.viewControllers.lastObject;
[[topController retain] autorelease];
UIViewController* poppedViewController = [self popViewControllerAnimated:NO];
[self pushViewController:controller animated:NO];
return poppedViewController;
}
@end
그런 다음 보기 컨트롤러에서 다음과 같이 위쪽 보기를 새 보기로 바꿀 수 있습니다.
[self.navigationController replaceTopViewControllerWithViewController: newController];
탐색 스택에 추가한 모든 보기 컨트롤러를 제공하는 탐색 보기 컨트롤러 배열을 확인할 수 있습니다.이 배열을 사용하면 특정 보기 컨트롤러로 다시 이동할 수 있습니다.
모노터치 / xamarin IOS의 경우:
UISplitViewController 클래스 내부;
UINavigationController mainNav = this._navController;
//List<UIViewController> controllers = mainNav.ViewControllers.ToList();
mainNav.ViewControllers = new UIViewController[] { };
mainNav.PushViewController(detail, true);//to have the animation
대신에,
사용할 수 있습니다.category해서를 self.navigationController되려고nil나고끝 popViewControllerAnimated
push 냥그툭치밀어, 이기쉬니우, 다할필없습니가요접근툭고에 접속할 필요가 .viewControllers....
// UINavigationController+Helper.h
@interface UINavigationController (Helper)
- (UIViewController*) popThenPushViewController:(UIViewController *)viewController animated:(BOOL)animated;
@end
// UINavigationController+Helper.m
@implementation UINavigationController (Helper)
- (UIViewController*) popThenPushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
UIViewController *v =[self popViewControllerAnimated:NO];
[self pushViewController:viewController animated:animated];
return v;
}
@end
View 컨트롤러에서
// #import "UINavigationController+Helper.h"
// invoke in your code
UIViewController *v= [[MyNewViewController alloc] init];
[self.navigationController popThenPushViewController:v animated:YES];
RELEASE_SAFELY(v);
정답은 아니지만 일부 시나리오(예: 내 시나리오)에서는 도움이 될 수 있습니다.
만약 당신이 뷰 컨트롤러 C를 Pop하고 A 대신 B(Out of Stack)로 가야 한다면, C 앞에 B를 푸시할 수 있으며, 3개 모두 스택에 있습니다.B 푸시를 보이지 않게 유지하고 C 또는 C와 B만 함께 팝업할지 여부를 선택하여 동일한 효과를 얻을 수 있습니다.
초기 문제 A -> C (나는 C를 터뜨리고 B를 보여주고 싶다, 스택에서 벗어남)
가능한 해결책 A -> B (보이지 않는 것을 누름) -> C (C를 팝할 때, 나는 B를 보여주거나 또한 팝할 것을 선택함)
이 솔루션을 사용하여 애니메이션을 유지합니다.
[self.navigationController pushViewController:controller animated:YES];
NSMutableArray *newControllers = [NSMutableArray arrayWithArray:self.navigationController.viewControllers];
[newControllers removeObject:newControllers[newControllers.count - 2]];
[self.navigationController setViewControllers:newControllers];
언급URL : https://stackoverflow.com/questions/410471/how-can-i-pop-a-view-from-a-uinavigationcontroller-and-replace-it-with-another-i
'programing' 카테고리의 다른 글
| mysql - DESCRIBE 테이블의 결과를 테이블에 저장하는 방법 (0) | 2023.08.15 |
|---|---|
| 레일에 종속성 주입이 있습니까? (0) | 2023.08.15 |
| JSPEL 식에서 Spring 보안 주체 가져오기 (0) | 2023.08.15 |
| 인터넷 뱅킹과 같은 보안 애플리케이션에서 AJAX를 많이 볼 수 없는 이유는 무엇입니까? (0) | 2023.08.15 |
| 모든 플랫폼에서 공유 싱글톤 구성 요소를 만드는 방법은 무엇입니까? (0) | 2023.08.15 |