在iOS 13之前,提供了用于覆盖整个屏幕的视图控制器。并且,在关闭后,将viewDidAppear
执行父视图控制器功能。
现在,iOS 13默认将表单显示为视图控制器,这意味着卡将部分覆盖基础视图控制器,这意味着viewDidAppear
不会被调用,因为父视图控制器从未真正消失过。
有没有一种方法可以检测到所显示的视图控制器工作表已被解雇?我可以在父视图控制器中重写某些其他功能,而不是使用某种委托?
在iOS 13之前,提供了用于覆盖整个屏幕的视图控制器。并且,在关闭后,将viewDidAppear
执行父视图控制器功能。
现在,iOS 13默认将表单显示为视图控制器,这意味着卡将部分覆盖基础视图控制器,这意味着viewDidAppear
不会被调用,因为父视图控制器从未真正消失过。
有没有一种方法可以检测到所显示的视图控制器工作表已被解雇?我可以在父视图控制器中重写某些其他功能,而不是使用某种委托?
Answers:
有没有一种方法可以检测到所显示的视图控制器工作表已被解雇?
是。
我可以在父视图控制器中重写某些其他功能,而不是使用某种委托?
不,“某种委托”是您的工作方式。使自己成为演示控制器的委托和重写presentationControllerDidDismiss(_:)
。
缺少一个一般的运行时生成的事件来通知您,所显示的视图控制器(无论是否为全屏)已被关闭,这确实很麻烦。但这不是一个新问题,因为始终存在非全屏显示的视图控制器。只是现在(在iOS 13中)有更多!我在其他地方对此主题进行了单独的问答:统一UIViewController“成为最前端”检测?。
这是父视图控制器的代码示例,当其以表单形式显示(即以默认的iOS 13方式)时,通知该视图控制器:
public final class Parent: UIViewController, UIAdaptivePresentationControllerDelegate
{
// This is assuming that the segue is a storyboard segue;
// if you're manually presenting, just see 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)原始提问者想在关闭工作表时获得一个函数调用(而他实现了presentationControllerDidAttemptToDismiss,当用户尝试并无法关闭工作表时会调用它),并且(b)设置isModalInPresentation是完全正交的,实际上会使所呈现的图纸不可忽略(这与OP想要的相反)。
另一个选择回来viewWillAppear
并viewDidAppear
设置
let vc = UIViewController()
vc.modalPresentationStyle = .fullScreen
此选项全屏显示,关闭后调用上述方法
对于将来的读者,这里是实现的更完整答案:
// Modal Dismiss iOS 13
modalNavController.presentationController?.delegate = modalVc
// 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)
}
}
self.isModalInPresentation = true
presentationControllerDidDismiss
应该有效
迅速
一般解决呼叫 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)
}
}
}
dismiss(_)
。
DRAG或CALL DISMISS 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!)
}
覆盖正在被关闭的UIViewController上的viewWillDisappear。它将通过isBeingDismissed
布尔标志提醒您被解雇。
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if isBeingDismissed {
print("user is dismissing the vc")
}
}
**如果用户在中途向下滑动并向后滑动卡时,即使卡未被取消,该卡仍会注册为已被取消。但这是一个极端情况,您可能并不在意。
self.dismiss(animated: Bool, completion: (() -> Void)?)
如果某人无权访问呈现的视图控制器,则他们可以在呈现视图控制器时重写以下方法,并将其更改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
}
如果在FullScreen中使用了ModalPresentationStyle,则控制器的行为将恢复为通常的状态。
ConsultarController controllerConsultar = this.Storyboard.InstantiateViewController(“ ConsultarController”)作为ConsultarController; controllerConsultar.ModalPresentationStyle = UIModalPresentationStyle.FullScreen; this.NavigationController.PushViewController(controllerConsultar,true);
从我的角度来看,苹果不应该设置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()
presentingViewController
不会触发viewWillAppear
viewWillAppear
从某种意义上说,依靠总是错误的。当然,我不喜欢Apple来跟从我下面挖开地板。但是正如我所说,我们只需要忍受这一点,并以新的方式做事。
presentedController
),并且都不知道确切是什么presentingViewController
。例如:在某些情况下,我必须使用UIViewController.topMostViewController()
它使我返回当前窗口中最顶级的视图控制器。因此,为什么我想做一些努力以保持当前行为在viewWillAppear
我的视图控制器中做正确的事情(刷新数据,UI)。如果您有解决此问题的想法,请提供帮助。