代码之家  ›  专栏  ›  技术社区  ›  Cheok Yan Cheng

从非全屏模式视图控制器中退出后,如何清除UITableViewController选择?[重复]

  •  -1
  • Cheok Yan Cheng  · 技术社区  · 4 年前

    在iOS 13之前,视图控制器通常覆盖整个屏幕。并且,当解除时,父视图控制器 viewDidAppear 函数被执行。

    现在iOS 13将把视图控制器显示为一张默认表,这意味着该卡将部分覆盖底层视图控制器,这意味着 视图没有出现 不会被调用,因为父视图控制器从未真正消失。

    有办法吗 检测显示的视图控制器工作表是否已取消 ? 我可以在父视图控制器中覆盖的其他一些功能 而不是使用某种委托 ?

    0 回复  |  直到 6 年前
        1
  •  82
  •   matt    6 年前

    是否有方法检测显示的视图控制器工作表已被取消?

    不,“某种形式的委托”是你做这件事的方式。让自己成为演示控制器的委托和替代 presentationControllerDidDismiss(_:) .

    https://developer.apple.com/documentation/uikit/uiadaptivepresentationcontrollerdelegate/3229889-presentationcontrollerdiddismiss


    缺少一般运行时生成的事件来通知您显示的视图控制器(无论是否全屏)已被取消,这确实很麻烦;但这并不是一个新问题,因为总是有非全屏显示的视图控制器。只是现在(在iOS 13中)它们的数量更多了!我在其他地方专门就这个话题提出了一个单独的问题和答案: Unified UIViewController "became frontmost" detection? .

        2
  •  52
  •   musical_coder    4 年前

    下面是一个父视图控制器的代码示例,它在显示子视图控制器时会收到通知 一张纸 (即,以默认的iOS 13方式)被解除:

    public final class Parent: UIViewController, UIAdaptivePresentationControllerDelegate
    {
      // This is assuming that the segue is a storyboard segue; 
      // if you're manually presenting, just set the delegate there.
      public override func prepare(for segue: UIStoryboardSegue, sender: Any?)
      {
        if segue.identifier == "mySegue" {
          segue.destination.presentationController?.delegate = self;
        }
      }
    
      public func presentationControllerDidDismiss(
        _ presentationController: UIPresentationController)
      {
        // Only called when the sheet is dismissed by DRAGGING.
        // You'll need something extra if you call .dismiss() on the child.
        // (I found that overriding dismiss in the child and calling
        // presentationController.delegate?.presentationControllerDidDismiss
        // works well).
      }
    }
    

    Jerland2的答案很混乱,因为(a)最初的提问者希望在填写表格时得到一个函数调用 解雇 (然而,他实现了PresentationControllerDidAttemptoDismiss,当用户尝试时调用它。) 失败了 (b)设置isModalInPresentation是完全正交的,事实上会使呈现的图纸不可拆卸(这与OP想要的相反)。

        3
  •  29
  •   PiterPan    6 年前

    另一个回去的选择 viewWillAppear viewDidAppear 一切就绪

    let vc = UIViewController()
    vc.modalPresentationStyle = .fullScreen
    

    此选项覆盖全屏,并在关闭后调用上述方法

        4
  •  26
  •   MobileMon    6 年前

    对于未来的读者,这里有一个更完整的答案:

    1. 在根视图控制器中,为segue添加以下内容(假设您的modal有导航控制器)
        // Modal Dismiss iOS 13
        modalNavController.presentationController?.delegate = modalVc
    
    1. 在模态视图控制器中添加以下委托+方法
    // MARK: - iOS 13 Modal (Swipe to Dismiss)
    
    extension ModalViewController: UIAdaptivePresentationControllerDelegate {
        func presentationControllerDidAttemptToDismiss(_ presentationController: UIPresentationController) {
    
    
            print("slide to dismiss stopped")
            self.dismiss(animated: true, completion: nil)
        }
    }
    
    1. 在模态视图控制器中,确保以下属性为真,以便调用委托方法
        self.isModalInPresentation = true
    
    1. 利润
        5
  •  8
  •   dimohamdy    5 年前

    敏捷的

    呼叫的一般解决方案 viewWillAppear 在里面 iOS13

    class ViewController: UIViewController {
    
            override func viewWillAppear(_ animated: Bool) {
                super.viewWillAppear(animated)
                print("viewWillAppear")
            }
    
            //Show new viewController
            @IBAction func show(_ sender: Any) {
                let newViewController = NewViewController()
                //set delegate of UIAdaptivePresentationControllerDelegate to self
                newViewController.presentationController?.delegate = self
                present(newViewController, animated: true, completion: nil)
            }
        }
    
        extension UIViewController: UIAdaptivePresentationControllerDelegate {
            public func presentationControllerDidDismiss( _ presentationController: UIPresentationController) {
                if #available(iOS 13, *) {
                    //Call viewWillAppear only in iOS 13
                    viewWillAppear(true)
                }
            }
        }
    
        6
  •  6
  •   Vitalii McCygnus    5 年前

    如果您想在用户从该工作表中关闭模式工作表时执行某些操作。 假设你已经有了一个带有 @IBAction 以及在关闭或执行其他操作之前显示警报的逻辑。你只想检测用户按下这样一个控制器的时刻。

    以下是方法:

    class MyModalSheetViewController: UIViewController {
    
         override func viewDidLoad() {
            super.viewDidLoad()
    
            self.presentationController?.delegate = self
         }
    
         @IBAction func closeAction(_ sender: Any) {
             // your logic to decide to close or not, when to close, etc.
         }
    
    }
    
    extension MyModalSheetViewController: UIAdaptivePresentationControllerDelegate {
    
        func presentationControllerShouldDismiss(_ presentationController: UIPresentationController) -> Bool {
            return false // <-prevents the modal sheet from being closed
        }
    
        func presentationControllerDidAttemptToDismiss(_ presentationController: UIPresentationController) {
            closeAction(self) // <- called after the modal sheet was prevented from being closed and leads to your own logic
        }
    }
    
        7
  •  6
  •   craft Taka    5 年前

    推翻 viewWillDisappear UIViewController 这件事被驳回了。它会提醒你通过 isBeingDismissed 布尔标志。

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
    
        if isBeingDismissed {
            print("user is dismissing the vc")
        }
    }
    

    **如果用户在向下刷卡的过程中刷了一半,然后又重新刷卡,即使卡没有被解除,它仍然会被注册为被解除。但这是一个你可能不关心的边缘案例。

        8
  •  4
  •   coders    6 年前

    拖动或调用Disclose FUNC将使用以下代码。

    1) 在根视图控制器中,您可以根据下面的代码判断哪个是它的表示视图控制器

     override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "presenterID" {
            let navigationController = segue.destination as! UINavigationController
            if #available(iOS 13.0, *) {
                let controller = navigationController.topViewController as! presentationviewcontroller
                // Modal Dismiss iOS 13
                controller.presentationController?.delegate = self
            } else {
                // Fallback on earlier versions
            }
            navigationController.presentationController?.delegate = self
    
        }
    }
    

    2) 同样,在根视图控制器中,您可以告诉用户当它的表示视图控制器失效时将执行什么操作

    public func presentationControllerDidDismiss(
      _ presentationController: UIPresentationController)
    {
        print("presentationControllerDidDismiss")
    }
    

    1) 在演示视图控制器中,当您点击此图片中的“取消”或“保存”按钮时。下面的代码将被调用。这个

    self.dismiss(animated: true) {
            self.presentationController?.delegate?.presentationControllerDidDismiss?(self.presentationController!)
        }
    

    enter image description here

        9
  •  1
  •   Alirezak    4 年前

    在SwiftUI中,可以使用onDismiss闭包

    func sheet<Item, Content>(item: Binding<Item?>, onDismiss: (() -> Void)?, content: (Item) -> Content) -> some View
    
        10
  •  0
  •   Kamran Khan    5 年前

    如果有人无权访问显示的视图控制器,他们可以在显示视图控制器时重写以下方法并更改 modalPresentationStyle fullScreen 或者可以使用这种方法添加上述策略之一

     override func present(_ viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Void)? = nil) {
        if let _ = viewControllerToPresent as? TargetVC {
            viewControllerToPresent.modalPresentationStyle = .fullScreen
        }
        super.present(viewControllerToPresent, animated: flag, completion: completion)
    }
    

    如果显示的视图控制器是导航控制器,并且您想检查根控制器,可以将上述条件更改为

    if let _ = (viewControllerToPresent as? UINavigationController)?.viewControllers.first as? TargetVC {
       viewControllerToPresent.modalPresentationStyle = .fullScreen
    }
    
        11
  •  -2
  •   Abelardo del angel Quiroz    5 年前

    如果在全屏中使用ModalPresentationStyle,控制器的行为将恢复正常。

    consultarcontrollerconsultar=这个。故事板。实例化EviewController(“ConsultarController”)作为ConsultarController; 控制员咨询。ModalPresentationStyle=UIModalPresentationStyle。全屏; 这导航控制器。PushView控制器(controllerConsultar,true);

        12
  •  -3
  •   jacob    6 年前

    在我看来,苹果不应该 pageSheet 这是默认值 modalPresentationStyle

    我想带上 fullScreen 通过使用 swizzling

    这样地:

    private func _swizzling(forClass: AnyClass, originalSelector: Selector, swizzledSelector: Selector) {
        if let originalMethod = class_getInstanceMethod(forClass, originalSelector),
           let swizzledMethod = class_getInstanceMethod(forClass, swizzledSelector) {
            method_exchangeImplementations(originalMethod, swizzledMethod)
        }
    }
    
    extension UIViewController {
    
        static func preventPageSheetPresentationStyle () {
            UIViewController.preventPageSheetPresentation
        }
    
        static let preventPageSheetPresentation: Void = {
            if #available(iOS 13, *) {
                _swizzling(forClass: UIViewController.self,
                           originalSelector: #selector(present(_: animated: completion:)),
                           swizzledSelector: #selector(_swizzledPresent(_: animated: completion:)))
            }
        }()
    
        @available(iOS 13.0, *)
        private func _swizzledPresent(_ viewControllerToPresent: UIViewController,
                                            animated flag: Bool,
                                            completion: (() -> Void)? = nil) {
            if viewControllerToPresent.modalPresentationStyle == .pageSheet
                       || viewControllerToPresent.modalPresentationStyle == .automatic {
                viewControllerToPresent.modalPresentationStyle = .fullScreen
            }
            _swizzledPresent(viewControllerToPresent, animated: flag, completion: completion)
        }
    }
    

    然后把这条线放到你的 AppDelegate

    UIViewController.preventPageSheetPresentationStyle()
    
        13
  •  -7
  •   Mikesch8764    6 年前

    调用presentingViewController不是很简单吗。你会出现吗? 解雇之前?

    self.presentingViewController?.viewWillAppear(false)
    self.dismiss(animated: true, completion: nil)