在 UIPageViewController 中包含的 ViewController 的委托获得 nil
Posted
技术标签:
【中文标题】在 UIPageViewController 中包含的 ViewController 的委托获得 nil【英文标题】:Got nil for delegate at ViewController included in UIPageViewController 【发布时间】:2019-12-22 18:19:52 【问题描述】:我有一个UIPageViewController
和几个ViewControllers
。我想使用委托协议从ViewController
在UIPageViewController
中执行一个功能。但是在delegate
中获取nil
。谁能确定我做错了什么?
PageViewController.swift
import UIKit
class PageViewController: UIPageViewController, UIPageViewControllerDelegate, UIPageViewControllerDataSource, Storyboarded
weak var coordinator: MainCoordinator?
lazy var orderedViewControllers: [UIViewController] =
return [self.newInstanceVC(viewController: "FirstLoadViewController"), self.newInstanceVC(viewController: "FirstLoad2ViewController")]
()
var pageControl = UIPageControl()
override func viewDidLoad()
super.viewDidLoad()
let storyboardVC = newInstanceVC(viewController: "FirstLoad2ViewController") as? FirstLoad2ViewController
storyboardVC?.delegate = self
self.dataSource = self
if let firstViewController = orderedViewControllers.first
setViewControllers([firstViewController], direction: .forward, animated: true, completion: nil)
self.delegate = self
configurePageControl()
func configurePageControl()
pageControl = UIPageControl(frame: CGRect(x: 0, y: UIScreen.main.bounds.maxY - 50, width: UIScreen.main.bounds.width, height: 50))
pageControl.numberOfPages = orderedViewControllers.count
pageControl.currentPage = 0
//pageControl.tintColor = .red
pageControl.pageIndicatorTintColor = .systemGray5
pageControl.currentPageIndicatorTintColor = .systemGray
self.view.addSubview(pageControl)
//return view controller by string identifier
func newInstanceVC(viewController: String) -> UIViewController
return UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: viewController)
//MARK: - Setup page controllers
// view controller that appears on swiping to the -> (left)
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController?
guard let viewControllerIndex = orderedViewControllers.firstIndex(of: viewController) else
return nil
let previousIndex = viewControllerIndex - 1
guard previousIndex >= 0 else
//return view controller from the end if it is last index from the left side (infinit scroll)
//return orderedViewControllers.last
return nil
guard orderedViewControllers.count >= previousIndex else
return nil
return orderedViewControllers[previousIndex]
// view controller that appears on swiping to the <- (right)
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController?
guard let viewControllerIndex = orderedViewControllers.firstIndex(of: viewController) else
return nil
let nextIndex = viewControllerIndex + 1
guard orderedViewControllers.count != nextIndex else
//return view controller from the begining if it is last index from the right side (infinit scroll)
//return orderedViewControllers.first
return nil
guard orderedViewControllers.count > nextIndex else
return nil
return orderedViewControllers[nextIndex]
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool)
//switch the bullet of the page
let pageContentVievController = pageViewController.viewControllers![0]
self.pageControl.currentPage = orderedViewControllers.firstIndex(of: pageContentVievController)!
extension PageViewController: PageViewDelegate
func handleButtonTap()
coordinator?.goToMainFromPresentation()
OneOfTheViewControllers.swift
import UIKit
protocol PageViewDelegate: class
func handleButtonTap()
class FirstLoad2ViewController: UIViewController, Storyboarded
weak var coordinator: MainCoordinator?
weak var child: ChildCoordinator?
weak var delegate: PageViewDelegate?
override func viewDidLoad()
super.viewDidLoad()
@IBAction func toMainScreenTap(_ sender: Any)
delegate!.handleButtonTap() //got nil for delegate here
【问题讨论】:
【参考方案1】:问题很简单,它隐藏在你的viewDidLoad()
方法里面PageViewController
...
override func viewDidLoad()
super.viewDidLoad()
let storyboardVC = newInstanceVC(viewController: "FirstLoad2ViewController") as? FirstLoad2ViewController
storyboardVC?.delegate = self
...
/// (storyboardVC) --- will be destroyed when out of viewDidLoad() scope.
那么,为什么你得到你的storyboardVC?.delegate = self
nil?因为您在 viewDidLoad()
方法中创建了 storyboardVC
属性,并且没有任何东西保留对它的引用。所以,最后 viewDidLoad()
方法它只是取消初始化以及它的 PageViewDelegate delegate
【讨论】:
好的。您对修复的建议是什么? @OlehH 我的建议是快速阅读有关内存管理的内容,这将对您有所帮助:docs.swift.org/swift-book/LanguageGuide/…以上是关于在 UIPageViewController 中包含的 ViewController 的委托获得 nil的主要内容,如果未能解决你的问题,请参考以下文章
在其中一个页面中包含的 UISwitch 上开始触摸时禁用 UIPageViewController 滚动
iOS - 如何在 UIPageViewController 中设置 UIScrollView 以在重新启用后开始滚动
从 UIPageViewContoller 中包含的视图设置 UINavigationBar 标题
UIPageControl(页面控件)不显示在 UIPageViewController