swift - 作为弹出窗口呈现的 UIViewController 可以是它自己的 popoverPresentationController 委托(delegate)吗?

标签 swift uiviewcontroller popover uipresentationcontroller

在下面显示的项目中,有一个 InitialViewController,其中有一个标记为“Show Popover”的按钮。当点击该按钮时,应用程序应该将第二个 View Controller (PopoverViewController)呈现为弹出窗口。第二个 View Controller 只有一个标签,上面写着“Popover!”。

storyboard image

如果 InitialViewController 负责实例化 PopoverViewController、检索 popoverPresentationController 然后设置 popoverPresentationController 的 delegate 自身(到 InitialViewController)。您可以在下面看到结果:

functiong app when delegation occurs in InitialViewController

但是,为了获得最大的可重用性,如果 InitialViewController 不需要了解有关如何委派演示 Controller 的任何信息,那就太好了。我认为 PopoverViewController 应该可以将自己设置为 popoverPresentationController 的 delegate。我已经在 PopoverViewControllerviewDidLoadviewWillAppear 函数中尝试过此操作。但是,PopoverViewController 在这两种情况下都是以模态方式呈现的,如下所示:

enter image description here

所有代码都包含在 InitialViewControllerPopoverViewController 中。 InitialViewController失败版本中使用的代码如下所示:

import UIKit

// MARK: - UIViewController subclass

class InitialViewController: UIViewController {

    struct Lets {
        static let storyboardName = "Main"
        static let popoverStoryboardID = "Popover View Controller"
    }

    @IBAction func showPopoverButton(_ sender: UIButton) {

        // instantiate & present the popover view controller
        let storyboard = UIStoryboard(name: Lets.storyboardName,
                                      bundle: nil )
        let popoverViewController =
            storyboard.instantiateViewController(withIdentifier: Lets.popoverStoryboardID )
        popoverViewController.modalPresentationStyle = .popover
        guard let popoverPresenter = popoverViewController.popoverPresentationController
            else {
                fatalError( "could not retrieve a pointer to the 'popoverPresentationController' property of popoverViewController")
        }
        present(popoverViewController,
                animated: true,
                completion: nil )

        // Retrieve and configure UIPopoverPresentationController
        // after presentation (per
        // https://developer.apple.com/documentation/uikit/uipopoverpresentationcontroller)

        popoverPresenter.permittedArrowDirections = .any
        let button = sender
        popoverPresenter.sourceView = button
        popoverPresenter.sourceRect = button.bounds

    }
}

失败 PopoverViewController 中的代码如下所示:

import UIKit


// MARK: - main UIViewController subclass

class PopoverViewController: UIViewController {

    // MARK: API
    var factorForMarginsAroundButton: CGFloat = 1.2

    // MARK: outlets and actions
    @IBOutlet weak var popoverLabel: UILabel!

    // MARK: lifecycle

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

        // set the preferred size for popover presentations
        let labelSize =
            popoverLabel.systemLayoutSizeFitting( UILayoutFittingCompressedSize )
        let labelWithMargins =
            CGSize(width: labelSize.width * factorForMarginsAroundButton,
                   height: labelSize.height * factorForMarginsAroundButton )
        preferredContentSize = labelWithMargins

        // set the delegate for the popoverPresentationController to self
        popoverPresentationController?.delegate = self

    }
}
// MARK: - UIPopoverPresentationControllerDelegate
//       (inherits from protocol UIAdaptivePresentationControllerDelegate)

extension PopoverViewController: UIPopoverPresentationControllerDelegate
{
    func adaptivePresentationStyle(for controller: UIPresentationController,
                                   traitCollection: UITraitCollection)
        -> UIModalPresentationStyle{
            return .none
    }
}

作为弹出窗口呈现的 View Controller 是否可以成为其自己的 popoverPresentationController 的委托(delegate)?

我使用的是 Xcode 8.0、Swift 3.1,目标是 iOS 10.0

最佳答案

这当然是可能的。你正在处理一个时间问题。您需要在viewWillAppear之前设置委托(delegate)。不幸的是,没有方便的 View 生命周期函数来插入分配,所以我这样做了。

在您的 PopoverViewController 类中,在重写的 getter 中分配委托(delegate)。如果您愿意,可以将分配设为有条件的。这会创建永久关系,因此其他代码永远不会通过分配委托(delegate)来“覆盖”委托(delegate)。

override var popoverPresentationController: UIPopoverPresentationController? {
    get {
        let ppc = super.popoverPresentationController
        ppc?.delegate = self
        return ppc
    }
}

关于swift - 作为弹出窗口呈现的 UIViewController 可以是它自己的 popoverPresentationController 委托(delegate)吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45469066/

相关文章:

在 uitableView 中删除行时 ios 应用程序崩溃

swift - 如何将数据作为时间戳数据类型发布到 Firestore - swift

ios - Objective-c : Pass value from AppDelegate to UIViewController

swift - 关闭 UIViewController 后 UI 卡住 5 秒

cocoa - iOS 7 : Restrict device current orientation when modal view controller is presented

javascript - 如何让 Twitter Bootstrap Popover 保持打开状态,直到鼠标移入其中?

ios - 在 UITextView 中以大写形式显示文本并从 shouldChangeText 获取新文本保持原始文本和输入文本的大小写

ios - 尝试快速更新 Realm 对象时获取 SIGABRT

ios - 从另一个类调用getter方法

ios - 从可重用 View 内部呈现弹出 View ?