Нет свайпа назад при скрытии панели навигации в UINavigationController

86

Мне нравится пакет swipe, унаследованный от встраивания ваших представлений в файл UINavigationController. К сожалению, я не могу найти способ скрыть, NavigationBarно все еще прокрутите сенсорную панель назад gesture. Я могу писать собственные жесты, но предпочитаю этого не делать и вместо этого полагаться на UINavigationControllerсмахивание назад gesture.

если я сниму флажок в раскадровке, обратное смахивание не будет работать

введите описание изображения здесь

в качестве альтернативы, если я программно скрою это, тот же сценарий.

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.navigationController setNavigationBarHidden:YES animated:NO]; // and animated:YES
}

Нет возможности спрятать верхнюю часть NavigationBarи по-прежнему смахивать?

Михай
источник
1
Допустимо ли добавление UIGestureRecognizer? Реализовать это несложно.
SwiftArchitect
1
@LancelotdelaMare, я пытался избежать этого, так как он не будет работать так же гладко, как обратный свайп UINavigationController. Я смотрю на UIScreenEdgePanGestureRecognizer, так как некоторые люди говорят, что это помогает, но еще не заставили его работать. Ищем здесь самое простое и элегантное решение.
mihai

Ответы:

96

Хак , который работает это установить interactivePopGestureRecognizerделегат «S из UINavigationControllerк nilтак:

[self.navigationController.interactivePopGestureRecognizer setDelegate:nil];

Но в некоторых ситуациях это могло вызвать странные эффекты.

HorseT
источник
16
«Повторное смахивание назад может привести к распознаванию жеста, когда в стеке есть только один контроллер представления, который, в свою очередь, переводит пользовательский интерфейс в (я думаю, неожиданное для инженеров UIKit) состояние, при котором он перестает распознавать какие-либо жесты»
HorseT,
4
Альтернатива , которая может защитить от неожиданного состояния было бы установить его на какой - либо объект низкого уровня (я использовал мое приложение делегата) и осуществить gestureRecognizerShouldBegin, возвращаясь , trueесли navigationController«s viewControllerсчета больше 0.
Kenny Уинкер
4
Хотя это работает, я НАСТОЯТЕЛЬНО рекомендую этого не делать. Нарушение делегата приводило к редкому и трудно определяемому блоку основного потока. Оказывается, это не основной блок потока, а то, что описал @HorseT.
Джош Бернфельд,
3
Мое приложение сохраняет дескриптор делегата, а затем восстанавливает его, viewWillDisappearи до сих пор не испытало побочных эффектов.
Don Park
1
!!!! Настоятельно не рекомендуется использовать это решение, при многократном использовании смахивания происходит странное поведение, задняя
панель
79

Проблемы с другими методами

Установка interactivePopGestureRecognizer.delegate = nilимеет непредвиденные побочные эффекты.

Настройка navigationController?.navigationBar.hidden = trueработает, но не позволяет скрыть изменения на панели навигации.

Наконец, как правило, лучше создать объект модели, предназначенный UIGestureRecognizerDelegateдля вашего контроллера навигации. Установка его на контроллер в UINavigationControllerстеке является причиной EXC_BAD_ACCESSошибок.

Полное решение

Сначала добавьте этот класс в свой проект:

class InteractivePopRecognizer: NSObject, UIGestureRecognizerDelegate {

    var navigationController: UINavigationController

    init(controller: UINavigationController) {
        self.navigationController = controller
    }

    func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        return navigationController.viewControllers.count > 1
    }

    // This is necessary because without it, subviews of your top controller can
    // cancel out your gesture recognizer on the edge.
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
}

Затем установите в контроллере навигации interactivePopGestureRecognizer.delegateэкземпляр вашего нового InteractivePopRecognizerкласса.

var popRecognizer: InteractivePopRecognizer?

override func viewDidLoad() {
    super.viewDidLoad()
    setInteractiveRecognizer()
}

private func setInteractiveRecognizer() {
    guard let controller = navigationController else { return }
    popRecognizer = InteractivePopRecognizer(controller: controller)
    controller.interactivePopGestureRecognizer?.delegate = popRecognizer
}

Наслаждайтесь скрытой панелью навигации без побочных эффектов, которая работает, даже если на вашем верхнем контроллере есть подвиды таблиц, коллекций или прокрутки.

Монах-охотник
источник
1
Отличное решение!
Мэтт Батлер,
1
Лучший ответ, спасибо!
Дори Дэниел
2
@HunterMaximillionMonk благодарит за отличное решение. Это работает как шарм
as diu
1
@HunterMaximillionMonk, похоже, работает правильно, но проблема с ним, когда у меня несколько контроллеров, а затем после одного всплытия он перестает работать.
Premal Khetani
1
Определенно лучший ответ!
daxh
54

В моем случае для предотвращения странных эффектов

Контроллер корневого представления

override func viewDidLoad() {
    super.viewDidLoad()

    // Enable swipe back when no navigation bar
    navigationController?.interactivePopGestureRecognizer?.delegate = self 

}


func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
    if(navigationController!.viewControllers.count > 1){
        return true
    }
    return false
}

http://www.gampood.com/pop-viewcontroller-with-out-navigation-bar/

саранпол
источник
2
Иногда я получаю EXC_BAD_ACCESS при использовании этого
Андрей Гордеев
Для меня это не делает жест работу и часто выходит из строя сEXEC_BAD_ACCESS
Benjohn
2
Не забудьте добавить UIGestureRecognizerDelegateк корневому контроллеру представления ... В моем случае делегат был установлен в nil в более позднем контроллере представления, чем контроллер корневого представления, поэтому при возврате к контроллеру корневого представления gestureRecognizerShouldBeginон не был вызван. Таким образом , я поместил .delegate = selfв viewDidAppear(). Это разрешило странные эффекты в моем случае .. Ура!
Wiingaard
@AndreyGordeev Не могли бы вы подробнее рассказать, когда это EXEC_BAD_ACCESSпроизойдет?
Jaybo
Подробнее об EXC_BAD_ACCESSошибке: stackoverflow.com/questions/28746123/…
Андрей Гордеев
25

Обновлено для iOS 13.4

iOS 13.4 сломала предыдущее решение, так что все будет ужасно. Похоже, что в iOS 13.4 это поведение теперь контролируется частным методом _gestureRecognizer:shouldReceiveEvent:(не путать с новым общедоступным shouldReceiveметодом, добавленным в iOS 13.4).


Я обнаружил, что другие опубликованные решения, переопределяющие делегата или устанавливающие для него значение nil, вызывают некоторое неожиданное поведение.

В моем случае, когда я был на вершине стека навигации и попытался использовать этот жест, чтобы открыть еще один, он потерпел неудачу (как и ожидалось), но последующие попытки вставить в стек начали вызывать странные графические сбои в Панель навигации. Это имеет смысл, потому что делегат используется для обработки большего, чем просто вопрос о том, следует ли блокировать распознавание жеста, когда панель навигации скрыта, и все это другое поведение было выброшено.

Судя по моему тестированию, похоже, что gestureRecognizer(_:, shouldReceiveTouch:)это метод, который реализует исходный делегат для блокировки распознавания жеста, когда панель навигации скрыта, а не gestureRecognizerShouldBegin(_:). Другие решения, которые реализуются gestureRecognizerShouldBegin(_:)в их делегированной работе, потому что отсутствие реализации gestureRecognizer(_:, shouldReceiveTouch:)вызовет поведение по умолчанию - получение всех касаний.

Решение @Nathan Perry приближается, но без реализации respondsToSelector(_:)код UIKit, который отправляет сообщения делегату, будет считать, что нет реализации ни для одного из других методов делегата, и forwardingTargetForSelector(_:)никогда не будет вызван.

Итак, мы берем на себя управление gestureRecognizer (_ :, shouldReceiveTouch :) в одном конкретном сценарии, в котором мы хотим изменить поведение, а в противном случае пересылаем все остальное делегату.

class AlwaysPoppableNavigationController : UINavigationController {

    private var alwaysPoppableDelegate: AlwaysPoppableDelegate!

    override func viewDidLoad() {
        super.viewDidLoad()

        self.alwaysPoppableDelegate = AlwaysPoppableDelegate(navigationController: self, originalDelegate: self.interactivePopGestureRecognizer!.delegate!)
        self.interactivePopGestureRecognizer!.delegate = self.alwaysPoppableDelegate
    }
}

private class AlwaysPoppableDelegate : NSObject, UIGestureRecognizerDelegate {

    weak var navigationController: AlwaysPoppableNavigationController?
    weak var originalDelegate: UIGestureRecognizerDelegate?

    init(navigationController: AlwaysPoppableNavigationController, originalDelegate: UIGestureRecognizerDelegate) {
        self.navigationController = navigationController
        self.originalDelegate = originalDelegate
    }

    // For handling iOS before 13.4
    @objc func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
        if let navigationController = navigationController, navigationController.isNavigationBarHidden && navigationController.viewControllers.count > 1 {
            return true
        }
        else if let originalDelegate = originalDelegate {
            return originalDelegate.gestureRecognizer!(gestureRecognizer, shouldReceive: touch)
        }
        else {
            return false
        }
    }

    // For handling iOS 13.4+
    @objc func _gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceiveEvent event: UIEvent) -> Bool {
        if let navigationController = navigationController, navigationController.isNavigationBarHidden && navigationController.viewControllers.count > 1 {
            return true
        }
        else if let originalDelegate = originalDelegate {
            let selector = #selector(_gestureRecognizer(_:shouldReceiveEvent:))
            if originalDelegate.responds(to: selector) {
                let result = originalDelegate.perform(selector, with: gestureRecognizer, with: event)
                return result != nil
            }
        }

        return false
    }

    override func responds(to aSelector: Selector) -> Bool {
        if #available(iOS 13.4, *) {
            // iOS 13.4+ does not need to override responds(to:) behavior, it only uses forwardingTarget
            return originalDelegate?.responds(to: aSelector) ?? false
        }
        else {
            if aSelector == #selector(gestureRecognizer(_:shouldReceive:)) {
                return true
            }
            else {
                return originalDelegate?.responds(to: aSelector) ?? false
            }
        }
    }

    override func forwardingTarget(for aSelector: Selector) -> Any? {
        if #available(iOS 13.4, *), aSelector == #selector(_gestureRecognizer(_:shouldReceiveEvent:)) {
            return nil
        }
        else {
            return self.originalDelegate
        }
    }
}
Крис Васселли
источник
1
Похоже, ваше решение на данный момент лучшее. Благодарность!
Тимур Берникович
«но последующие попытки поместить в стек начнут вызывать странные графические сбои в панели навигации» - я здесь запутался. Я думал, у нас нет панели навигации? Вот в чем вопрос? В моей ситуации у меня есть контроллер навигации, встроенный как дочерний контроллер представления без панели навигации; содержащий VC имеет элементы управления навигацией. Итак, я позволил содержащемуся VC быть делегатом распознавателя и просто сделал gestureRecognizerShouldBegin:это, и это "похоже на работу". Интересно, стоит ли мне искать.
skagedal 02
2
Это была утечка памяти, так как это navigationControllerбыла сильная ссылка в AlwaysPoppableDelegate. Я отредактировал код, чтобы сделать его weakссылкой.
Graham Perks
3
Это приятное решение больше не работает в iOS 13.4
Эли
@ChrisVasselli Действительно круто, спасибо! Надеюсь, это пройдет проверку частных методов обзора App Store.
Эли
16

Вы можете создать подкласс UINavigationController следующим образом:

@interface CustomNavigationController : UINavigationController<UIGestureRecognizerDelegate>

@end

Реализация:

@implementation CustomNavigationController

- (void)setNavigationBarHidden:(BOOL)hidden animated:(BOOL)animated {
    [super setNavigationBarHidden:hidden animated:animated];
    self.interactivePopGestureRecognizer.delegate = self;
}

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
    if (self.viewControllers.count > 1) {
        return YES;
    }
    return NO;
}

@end
Йогеш Махешвари
источник
2
Использование этого подхода позволяет разбить всплывающий жест на UIPageViewControllerпрокрутку.
атулхатри
Я обнаружил, что необходима проверка viewController.count> 1. Если пользователь попытается выполнить обратное смахивание только с корневым виртуальным каналом, пользовательский интерфейс зависнет при следующем нажатии виртуального канала.
VaporwareWolf
11

Простой ответ без побочных эффектов

Хотя большинство ответов здесь хороши, они, по-видимому, имеют непредвиденные побочные эффекты (нарушение работы приложения) или являются подробными.

Самым простым, но функциональным решением, которое я смог придумать, было следующее:

В ViewController, в котором вы скрываете панель навигации,

class MyNoNavBarViewController: UIViewController {
    
    // needed for reference when leaving this view controller
    var initialInteractivePopGestureRecognizerDelegate: UIGestureRecognizerDelegate?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // we will need a reference to the initial delegate so that when we push or pop.. 
        // ..this view controller we can appropriately assign back the original delegate
        initialInteractivePopGestureRecognizerDelegate = self.navigationController?.interactivePopGestureRecognizer?.delegate
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(true)

        // we must set the delegate to nil whether we are popping or pushing to..
        // ..this view controller, thus we set it in viewWillAppear()
        self.navigationController?.interactivePopGestureRecognizer?.delegate = nil
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(true)

        // and every time we leave this view controller we must set the delegate back..
        // ..to what it was originally
        self.navigationController?.interactivePopGestureRecognizer?.delegate = initialInteractivePopGestureRecognizerDelegate
    }
}

В других ответах предлагалось просто установить делегата на ноль. Переход назад к исходному контроллеру представления в стеке навигации приводит к отключению всех жестов. Возможно, какой-то надзор со стороны разработчиков UIKit / UIGesture.

Кроме того, некоторые ответы здесь, которые я реализовал, привели к нестандартному поведению навигации Apple (в частности, позволяя прокручивать вверх или вниз, а также прокручивать назад). Эти ответы также кажутся немного многословными и в некоторых случаях неполными.

CodyB
источник
viewDidLoad()это не лучшее место для захвата, initialInteractivePopGestureRecognizerDelegateтак как там navigationControllerможет быть ноль (еще не помещено в стек). viewWillAppearместа, где вы скрываете панель навигации, было бы более подходящим
nCod3d
10

Строительство из на ответе Хантера Максимиллиона Монка , я создал подкласс для UINavigationController, а затем установил собственный класс для моего UINavigationController в моей раскадровке. Окончательный код для двух классов выглядит так:

InteractivePopRecognizer:

class InteractivePopRecognizer: NSObject {

    // MARK: - Properties

    fileprivate weak var navigationController: UINavigationController?

    // MARK: - Init

    init(controller: UINavigationController) {
        self.navigationController = controller

        super.init()

        self.navigationController?.interactivePopGestureRecognizer?.delegate = self
    }
}

extension InteractivePopRecognizer: UIGestureRecognizerDelegate {
    func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        return (navigationController?.viewControllers.count ?? 0) > 1
    }

    // This is necessary because without it, subviews of your top controller can cancel out your gesture recognizer on the edge.
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
}

HiddenNavBarNavigationController:

class HiddenNavBarNavigationController: UINavigationController {

    // MARK: - Properties

    private var popRecognizer: InteractivePopRecognizer?

    // MARK: - Lifecycle

    override func viewDidLoad() {
        super.viewDidLoad()
        setupPopRecognizer()
    }

    // MARK: - Setup

    private func setupPopRecognizer() {
        popRecognizer = InteractivePopRecognizer(controller: self)
    }
}

Раскадровка:

Пользовательский класс контроллера навигации раскадровки

Tylermilner
источник
8

Похоже, решение, предоставленное @ChrisVasseli, является лучшим. Я хотел бы предложить такое же решение в Objective-C, потому что вопрос касается Objective-C (см. Теги)

@interface InteractivePopGestureDelegate : NSObject <UIGestureRecognizerDelegate>

@property (nonatomic, weak) UINavigationController *navigationController;
@property (nonatomic, weak) id<UIGestureRecognizerDelegate> originalDelegate;

@end

@implementation InteractivePopGestureDelegate

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
    if (self.navigationController.navigationBarHidden && self.navigationController.viewControllers.count > 1) {
        return YES;
    } else {
        return [self.originalDelegate gestureRecognizer:gestureRecognizer shouldReceiveTouch:touch];
    }
}

- (BOOL)respondsToSelector:(SEL)aSelector
{
    if (aSelector == @selector(gestureRecognizer:shouldReceiveTouch:)) {
        return YES;
    } else {
        return [self.originalDelegate respondsToSelector:aSelector];
    }
}

- (id)forwardingTargetForSelector:(SEL)aSelector
{
    return self.originalDelegate;
}

@end

@interface NavigationController ()

@property (nonatomic) InteractivePopGestureDelegate *interactivePopGestureDelegate;

@end

@implementation NavigationController

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.interactivePopGestureDelegate = [InteractivePopGestureDelegate new];
    self.interactivePopGestureDelegate.navigationController = self;
    self.interactivePopGestureDelegate.originalDelegate = self.interactivePopGestureRecognizer.delegate;
    self.interactivePopGestureRecognizer.delegate = self.interactivePopGestureDelegate;
}

@end
Тимур Берникович
источник
3
Потому что ObjC еще не умер! 😉
MonsieurDart
2
Это правильное решение. Любое другое решение, которое не пересылается исходному делегату, неверно.
Джош Бернфельд
6

Мое решение - напрямую расширить UINavigationControllerкласс:

import UIKit

extension UINavigationController: UIGestureRecognizerDelegate {

    override open func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        self.interactivePopGestureRecognizer?.delegate = self
    }

    public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        return self.viewControllers.count > 1
    }

}

Таким образом, все контроллеры навигации будут отключены путем скольжения.

Fredericdnd
источник
Как ни странно, это приводит viewDidAppearк игнорированию всех вызовов VC, принадлежащих любому контроллеру навигации.
cumanzor
4

Вы можете сделать это с помощью прокси-делегата. Когда вы создаете контроллер навигации, возьмите существующий делегат. И передаем в прокси. Затем передайте все методы делегата существующему делегату, кроме gestureRecognizer:shouldReceiveTouch:использованияforwardingTargetForSelector:

Настроить:

let vc = UIViewController(nibName: nil, bundle: nil)
let navVC = UINavigationController(rootViewController: vc)
let bridgingDelegate = ProxyDelegate()
bridgingDelegate.existingDelegate = navVC.interactivePopGestureRecognizer?.delegate
navVC.interactivePopGestureRecognizer?.delegate = bridgingDelegate

Прокси-делегат:

class ProxyDelegate: NSObject, UIGestureRecognizerDelegate {
    var existingDelegate: UIGestureRecognizerDelegate? = nil

    override func forwardingTargetForSelector(aSelector: Selector) -> AnyObject? {
        return existingDelegate
    }

    func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
        return true
    }  
}
Натан Перри
источник
Это настоящий ответ в стиле Obj-C!
Sound Blaster,
forwardingTargetForSelector сэкономил бы мне столько времени на прошлом проекте, если бы я знал об этом. Хорошая вещь!
VaporwareWolf
4

Ответ Hunter Monk действительно потрясающий, но, к сожалению, в iOS 13.3.1 он не работает.

Я объясню еще один способ спрятаться UINavigationBarи не проиграть swipe to back gesture. Я тестировал iOS 13.3.1 и 12.4.3, и все работает.

Вам нужно создать собственный класс UINavigationControllerи установить этот класс UINavigationControllerвStoryboard

Установите для настраиваемого класса значение <code> UINavigationController </code>

Не скрывайте NavigationBarнаStoryboard

<code> UINavigationController </code> Инспектор атрибутов:

Пример на Storyboard:

Раскадровка:

И, наконец, вставьте это: navigationBar.isHidden = truein viewDidLoadofCustomNavigationController класса.

Убедитесь, что НЕ используйте этот метод setNavigationBarHidden(true, animated: true)для скрытия файлов NavigationBar.

import UIKit

class CustomNavigationController: UINavigationController {

    override func viewDidLoad() {
        super.viewDidLoad()

        navigationBar.isHidden = true
    }
}
Юсуф Сайти
источник
2
Я тестировал это на реальном устройстве iPhone 6S Plus, iOS 13.4.1и смахивание назад работает.
Эмре Айдин,
1
работает также на новейшей iOS 14.0.1
bezoadam
1

Ответ Xamarin:

Реализация IUIGestureRecognizerDelegateинтерфейса в определении класса ViewController в:

public partial class myViewController : UIViewController, IUIGestureRecognizerDelegate

В вашем ViewController добавьте следующий метод:

[Export("gestureRecognizerShouldBegin:")]
public bool ShouldBegin(UIGestureRecognizer recognizer) {
  if (recognizer is UIScreenEdgePanGestureRecognizer && 
      NavigationController.ViewControllers.Length == 1) {
    return false;
  }
  return true;
}

В вашем ViewController ViewDidLoad()добавьте следующую строку:

NavigationController.InteractivePopGestureRecognizer.Delegate = this;
Ахмад
источник
Предположительно это находится в UINavigationControllerконтроллере корневого представления? Я получаю, EXEC_BAD_ACCESSкогда пробую это.
Benjohn
Вы можете панорамировать края на контроллере корневого представления? Это не должно быть возможным, потому что, когда вы находитесь в корневом VC, вы открыли все другие VC, а длина массива VC вашего Nav должна быть 1.
Ахмад
Сбой происходит до вызова gestureRecognizerShouldBegin:.
Benjohn,
1
Можете ли вы опубликовать свой код VC в новом вопросе или на форумах Xamarin?
Ахмад
Нет, не видел. Думаю, оставлю на .1!
Benjohn
1

Я пробовал это, и он отлично работает: как скрыть панель навигации, не теряя возможности скольжения

Идея состоит в том, чтобы реализовать «UIGestureRecognizerDelegate» в вашем .h и добавить его в ваш .m-файл.

- (void)viewWillAppear:(BOOL)animated {
// hide nav bar
[[self navigationController] setNavigationBarHidden:YES animated:YES];

// enable slide-back
if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
    self.navigationController.interactivePopGestureRecognizer.enabled = YES;
    self.navigationController.interactivePopGestureRecognizer.delegate = self;
  }
}

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
   return YES;  
}
Каримихаб
источник
1

Вот мое решение: я меняю альфа-канал на панели навигации, но панель навигации не скрывается. Все мои контроллеры представления являются подклассом моего BaseViewController, и у меня есть:

    override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    navigationController?.navigationBar.alpha = 0.0
}

Вы также можете создать подкласс UINavigationController и поместить туда этот метод.

Младен Ивастинович
источник
0

Некоторым людям удалось вместо этого вызвать setNavigationBarHiddenметод с анимацией YES.

Mundi
источник
Мне не повезло. Обновляю свой ответ, чтобы охватить это предложение.
mihai
0

В моем представлении контроллер без панели навигации я использую

open override func viewWillAppear(_ animated: Bool) {
  super.viewWillAppear(animated)

  CATransaction.begin()
  UIView.animate(withDuration: 0.25, animations: { [weak self] in
    self?.navigationController?.navigationBar.alpha = 0.01
  })
  CATransaction.commit()
}

open override func viewWillDisappear(_ animated: Bool) {
  super.viewWillDisappear(animated)
  CATransaction.begin()
  UIView.animate(withDuration: 0.25, animations: { [weak self] in
    self?.navigationController?.navigationBar.alpha = 1.0
  })
  CATransaction.commit()
}

Во время интерактивного увольнения кнопка назад будет светиться, поэтому я ее спрятал.

кодировщик фруктов
источник
-2

Есть действительно простое решение, которое я пробовал и отлично работает, оно есть в Xamarin.iOS, но его можно применить и к нативному:

    public override void ViewWillAppear(bool animated)
    {
        base.ViewWillAppear(animated);
        this.NavigationController.SetNavigationBarHidden(true, true);
    }

    public override void ViewDidAppear(bool animated)
    {
        base.ViewDidAppear(animated);
        this.NavigationController.SetNavigationBarHidden(false, false);
        this.NavigationController.NavigationBar.Hidden = true;
    }

    public override void ViewWillDisappear(bool animated)
    {
        base.ViewWillDisappear(animated);
        this.NavigationController.SetNavigationBarHidden(true, false);
    }
Жоао Пальма
источник
-6

Вот как отключить распознаватель жестов, когда пользователь выходит из ViewController. Вы можете вставить его в свой viewWillAppear () или в свои методы ViewDidLoad ().

if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
    self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}
Эддвин Пас
источник
Пожалуйста, прочтите вопрос перед тем, как публиковать ответы. Вопрос был в том, чтобы включить, а не отключить. МЫ ЛЮБИМ ЖЕСТ ПОПА.
Йогеш Махешвари