作为弹出窗口呈现的 UIViewController 可以是它自己的 popoverPresentationController 委托吗?
Can a UIViewController that is presented as a popover be its own popoverPresentationController delegate?
在下面显示的项目中有一个 InitialViewController
,它有一个标记为 "Show Popover" 的按钮。当点击该按钮时,应用程序应该将第二个视图控制器(PopoverViewController
)显示为弹出窗口。第二个视图控制器只有一个标签,上面写着 "Popover!".
如果 InitialViewController
负责实例化 PopoverViewController
、检索 popoverPresentationController
然后将 popoverPresentationController 的 delegate
设置为自身(到 InitialViewController
).您可以在下面看到结果:
但是,为了最大限度地提高可重用性,如果 InitialViewController
不需要了解有关如何委派表示控制器的任何信息,那就太好了。我认为 PopoverViewController
应该可以将自己设置为 popoverPresentationController 的 delegate
。我已经在 PopoverViewController
的 viewDidLoad
或 viewWillAppear
函数中试过了。然而,PopoverViewController
在这两种情况下都是模态呈现的,如下所示:
所有代码仅包含在 InitialViewController
和 PopoverViewController
中。 InitialViewController
的failing版本使用的代码如下所示:
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
}
}
作为弹出窗口呈现的视图控制器是否可以成为其自身 popoverPresentationController
的委托?
我正在使用 Xcode 8.0,Swift 3.1,目标是 iOS 10.0
当然有可能。您正在处理时间问题。您需要在 viewWillAppear
之前设置委托。不幸的是,没有方便的视图生命周期函数来插入赋值,所以我改为这样做。
在您的 PopoverViewController
class 中,在覆盖 getter 中分配委托。如果您愿意,可以使分配有条件。这会创建一个永久关系,因此其他代码永远不会 "override" 通过分配它来委托。
override var popoverPresentationController: UIPopoverPresentationController? {
get {
let ppc = super.popoverPresentationController
ppc?.delegate = self
return ppc
}
}
在下面显示的项目中有一个 InitialViewController
,它有一个标记为 "Show Popover" 的按钮。当点击该按钮时,应用程序应该将第二个视图控制器(PopoverViewController
)显示为弹出窗口。第二个视图控制器只有一个标签,上面写着 "Popover!".
如果 InitialViewController
负责实例化 PopoverViewController
、检索 popoverPresentationController
然后将 popoverPresentationController 的 delegate
设置为自身(到 InitialViewController
).您可以在下面看到结果:
但是,为了最大限度地提高可重用性,如果 InitialViewController
不需要了解有关如何委派表示控制器的任何信息,那就太好了。我认为 PopoverViewController
应该可以将自己设置为 popoverPresentationController 的 delegate
。我已经在 PopoverViewController
的 viewDidLoad
或 viewWillAppear
函数中试过了。然而,PopoverViewController
在这两种情况下都是模态呈现的,如下所示:
所有代码仅包含在 InitialViewController
和 PopoverViewController
中。 InitialViewController
的failing版本使用的代码如下所示:
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
}
}
作为弹出窗口呈现的视图控制器是否可以成为其自身 popoverPresentationController
的委托?
我正在使用 Xcode 8.0,Swift 3.1,目标是 iOS 10.0
当然有可能。您正在处理时间问题。您需要在 viewWillAppear
之前设置委托。不幸的是,没有方便的视图生命周期函数来插入赋值,所以我改为这样做。
在您的 PopoverViewController
class 中,在覆盖 getter 中分配委托。如果您愿意,可以使分配有条件。这会创建一个永久关系,因此其他代码永远不会 "override" 通过分配它来委托。
override var popoverPresentationController: UIPopoverPresentationController? {
get {
let ppc = super.popoverPresentationController
ppc?.delegate = self
return ppc
}
}