UIViewController가 탐색 스택에서 Popped를 가져 오는지 확인하고 있습니까?
작업을 수행 할 수 있도록 뷰 컨트롤러가 내비게이션 스택에서 터질 때를 알아야합니다.
-viewWillDisappear를 사용할 수 없습니다. 왜냐하면 뷰 컨트롤러가 어떤 이유로 든 화면 밖으로 이동할 때 호출되기 때문입니다 (새 뷰 컨트롤러가 맨 위에 눌려지는 것과 같이).
특히 컨트롤러가 저절로 터질 때를 알아야합니다.
미리 감사드립니다.
이에 대한 명시적인 메시지가 있다고 생각하지 않지만 UINavigationController를 하위 클래스 화하고 popViewControllerAnimated를 재정의 할 수 있습니다 (내가 시도해 본 적이 없음).
또는 뷰 컨트롤러에 대한 다른 참조가없는 경우-dealloc에 추가 할 수 있습니까?
viewWillDisappear
제시된 VC에서 메서드를 재정의 한 다음 isMovingFromParentViewController
재정의 내에서 플래그 를 확인하고 특정 논리를 수행합니다. 제 경우에는 탐색 컨트롤러 도구 모음을 숨기고 있습니다. 제시된 VC가 완벽하지는 않지만 밀려났다는 것을 이해해야합니다.
의 사용자 정의 하위 클래스에서 willMoveToParentViewController:
(대신 viewWillDisappear:
) 재정의 해보 십시오 UIViewController
.
뷰 컨트롤러가 컨테이너 뷰 컨트롤러에서 추가되거나 제거되기 직전에 호출됩니다.
- (void)willMoveToParentViewController:(UIViewController *)parent
{
[super willMoveToParentViewController:parent];
if (!parent) {
// `self` is about to get popped.
}
}
다행히도 viewWillDisappear 메서드가 호출 될 즈음에는 viewController가 이미 스택에서 제거 되었기 때문에 viewController가 더 이상 self.navigationController.viewControllers 에 없기 때문에 팝업되는 것을 알 수 있습니다.
스위프트 4
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if let nav = self.navigationController {
let isPopping = !nav.viewControllers.contains(self)
if isPopping {
// popping off nav
} else {
// on nav, not popping off (pushing past, being presented over, etc.)
}
} else {
// not on nav at all
}
}
원래 코드
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
if ((self.navigationController) &&
(![self.navigationController.viewControllers containsObject:self])) {
NSLog(@"I've been popped!");
}
}
이것은 나를 위해 일하고 있습니다.
- (void)viewDidDisappear:(BOOL)animated
{
if (self.parentViewController == nil) {
NSLog(@"viewDidDisappear doesn't have parent so it's been popped");
//release stuff here
} else {
NSLog(@"PersonViewController view just hidden");
}
}
여기서 잡을 수 있습니다.
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
if (viewController == YourAboutToAppearController) {
// do something
}
}
이것은 새로운 뷰가 표시되기 직전에 실행됩니다. 아직 아무도 움직이지 않았습니다. 나는 asinine NavigationController 앞에서 마술을하기 위해 항상 사용합니다. 제목과 버튼 제목을 설정하고 거기에서 무엇이든 할 수 있습니다.
나도 같은 문제를 안고있어. 나는 viewDisdisappear로 시도했지만 함수가 호출되지 않았습니다. (아마도 모든 VC가 UITableViewController이기 때문에 이유를 모르겠습니다.) Alex의 제안은 잘 작동하지만 탐색 컨트롤러가 아래에 표시되면 실패합니다. 더 많은 탭.이 경우 내비게이션 컨트롤러의 모든 VC에는 하위 클래스로 분류 한 내비게이션 컨트롤러가 아닌 UIMoreNavigationController로 navigationController가 있으므로 VC가 터질 때 nav에서 알림을받지 못합니다.
마침내 문제를 해결했습니다. UINavigationController 범주로 다시 작성하십시오-(UIViewController *) popViewControllerAnimated : (BOOL) animated
- (UIViewController *)popViewControllerAnimated:(BOOL)animated{
NSLog(@"UINavigationController(Magic)");
UIViewController *vc = self.topViewController;
if ([vc respondsToSelector:@selector(viewControllerWillBePopped)]) {
[vc performSelector:@selector(viewControllerWillBePopped)];
}
NSArray *vcs = self.viewControllers;
UIViewController *vcc = [vcs objectAtIndex:[vcs count] - 2];
[self popToViewController:vcc animated:YES];
return vcc;}
그것은 나를 위해 잘 작동합니다 : D
나는 이것을 시도했다 :
- (void) viewWillDisappear:(BOOL)animated {
// If we are disappearing because we were removed from navigation stack
if (self.navigationController == nil) {
// YOUR CODE HERE
}
[super viewWillDisappear:animated];
}
아이디어는 팝업시 뷰 컨트롤러의 navigationController가 nil로 설정된다는 것입니다. 따라서 뷰가 사라지고 더 이상 navigationController가 있으면 팝업되었다고 결론을 내 렸습니다. (다른 시나리오에서는 작동하지 않을 수 있습니다).
viewWillDisappear가 문서에서 언급되지 않았기 때문에 팝업시 호출된다는 것을 보증 할 수 없습니다. 나는보기가 평면도 일 때, 그리고 평면도 아래에서 그것을 시도했습니다.
행운을 빕니다, 오데드.
하위 클래스 UINavigationController
및 재정의 popViewController
:
스위프트 3
protocol CanPreventPopProtocol {
func shouldBePopped() -> Bool
}
class MyNavigationController: UINavigationController {
override func popViewController(animated: Bool) -> UIViewController? {
let viewController = self.topViewController
if let canPreventPop = viewController as? CanPreventPopProtocol {
if !canPreventPop.shouldBePopped() {
return nil
}
}
return super.popViewController(animated: animated)
}
//important to prevent UI thread from freezing
//
//if popViewController is called by gesture recognizer and prevented by returning nil
//UI will freeze after calling super.popViewController
//so that, in order to solve the problem we should not return nil from popViewController
//we interrupt the call made by gesture recognizer to popViewController through
//returning false on gestureRecognizerShouldBegin
//
//tested on iOS 9.3.2 not others
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
let viewController = self.topViewController
if let canPreventPop = viewController as? CanPreventPopProtocol {
if !canPreventPop.shouldBePopped() {
return false
}
}
return true
}
}
이것을 사용할 수 있습니다.
if(self.isMovingToParentViewController)
{
NSLog(@"Pushed");
}
else
{
NSLog(@"Popped");
}
UINavigationBarDelegate의 navigationBar : shouldPopItem 프로토콜 메서드를 사용할 수 있습니다.
([self.navigationController.viewControllers indexOfObject : self] == NSNotFound) {//이 뷰가 터진 경우 viewwilldisappear에서이 확인을 시도합니다. }
알림을 관찰 할 수 있습니다.
- (void)viewDidLoad{
[super viewDidLoad];
[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(navigationControllerWillShowViewController:) name:@"UINavigationControllerWillShowViewControllerNotification" object:nil];
}
- (void)navigationControllerDidShowViewController:(NSNotification *)notification{
UIViewController *lastVisible = notification.userInfo[@"UINavigationControllerLastVisibleViewController"];
if(lastVisible == self){
// we are being popped
}
}
I needed to also prevent from popping sometimes so the best answer for me was written by Orkhan Alikhanov. But it did not work because the delegate was not set, so I made the final version:
import UIKit
class CustomActionsNavigationController: UINavigationController,
UIGestureRecognizerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
interactivePopGestureRecognizer?.delegate = self
}
override func popViewController(animated: Bool) -> UIViewController? {
if let delegate = topViewController as? CustomActionsNavigationControllerDelegate {
guard delegate.shouldPop() else { return nil }
}
return super.popViewController(animated: animated)
}
// important to prevent UI thread from freezing
//
// if popViewController is called by gesture recognizer and prevented by returning nil
// UI will freeze after calling super.popViewController
// so that, in order to solve the problem we should not return nil from popViewController
// we interrupt the call made by gesture recognizer to popViewController through
// returning false on gestureRecognizerShouldBegin
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
if let delegate = topViewController as? CustomActionsNavigationControllerDelegate {
if !delegate.shouldPop() {
return false
}
}
// This if statement prevents navigation controller to pop when there is only one view controller
if viewControllers.count == 1 {
return false
}
return true
}
}
protocol CustomActionsNavigationControllerDelegate {
func shouldPop() -> Bool
}
UPDATE
I have added viewControllers.count == 1
case, because if there is one controller in the stack and user makes the gesture, it will freeze the UI of your application.
'developer tip' 카테고리의 다른 글
Angular2 : 정의되지 않은 '이름'속성을 읽을 수 없습니다. (0) | 2020.12.14 |
---|---|
MySql 5.7 설치 프로그램이 VS 2013 재배포 가능 패키지를 감지하지 못함 (0) | 2020.12.14 |
C #을 사용하여 각 단어의 첫 문자 또는 전체 문자열의 첫 문자를 대문자로 바꾸는 방법은 무엇입니까? (0) | 2020.12.14 |
Python, 기본 인증을 사용하는 HTTPS GET (0) | 2020.12.14 |
텍스트 편집시 자동 초점 비활성화 (0) | 2020.12.14 |