viewWillAppear 没有在 UIPageViewController 孩子上被调用
Posted
技术标签:
【中文标题】viewWillAppear 没有在 UIPageViewController 孩子上被调用【英文标题】:viewWillAppear not getting called on UIPageViewController child 【发布时间】:2018-09-28 12:02:25 【问题描述】:所以我有 UIPageViewController 和 2 个 UIViewControllers。我想知道它们中的每一个何时显示,但切换时不会调用 viewWillAppear 或 didAppear 。除了检查 UIPageViewController 中的滑动之外,有谁知道为什么不或如何知道他们何时被滑动?
class HomePageViewController: UIPageViewController
weak var homePageDelegate: HomePageViewControllerDelegate?
var sequenceControl: PageContainerViewController!
var chatControl: PageContainerViewController!
var directControl: PageContainerViewController!
var lastShownControl: PageContainerViewController!
private var partnerConnectionChanged = true
private(set) lazy var soloViewControllers: Array<UIViewController> =
return loadViews(for: .solo)
()
private(set) lazy var partnerViewControllers: Array<UIViewController> =
return loadViews(for: .partner)
()
override func viewDidLoad()
super.viewDidLoad()
dataSource = self
delegate = self
WebSocketController.sharedInstance.add(self)
prepareViews()
if let initialViewController = getViewsList().first
scrollToViewController(viewController: initialViewController)
homePageDelegate?.homePageViewController(homePageViewController: self, didUpdatePageCount: getViewsList().count)
override func viewWillAppear(_ animated: Bool)
if (FlowController.sharedInstance.showDeviceConnect)
navigationController?.popViewController(animated: false)
override var preferredStatusBarStyle: UIStatusBarStyle
return UIStatusBarStyle.lightContent
func prepareViews()
sequenceControl = storyboard?.instantiateViewController(withIdentifier: "pageContainerIdentifier") as? PageContainerViewController
sequenceControl.setViewOption(to: .sequenceView, with: self)
chatControl = storyboard?.instantiateViewController(withIdentifier: "pageContainerIdentifier") as? PageContainerViewController
chatControl.setViewOption(to: .chatView, with: self)
directControl = storyboard?.instantiateViewController(withIdentifier: "pageContainerIdentifier") as? PageContainerViewController
directControl.setViewOption(to: .directControlView, with: self)
func loadViews(for arrayType: ArrayType) -> Array<UIViewController>
var viewContainers = Array<UIViewController>()
viewContainers.append(sequenceControl)
if(arrayType == .partner)
viewContainers.append(chatControl)
viewContainers.append(directControl)
return viewContainers
func getViewsList() -> [UIViewController]
if (WebSocketController.sharedInstance.partnerConnected)
return partnerViewControllers
else
return soloViewControllers
//MARK: - Page Controller
/**
Scrolls to the next view controller.
*/
public func scrollToNextViewController()
if let visibleViewController = viewControllers?.first,
let nextViewController = pageViewController(self, viewControllerAfter: visibleViewController)
scrollToViewController(viewController: nextViewController)
/**
Scrolls to the previous view controller.
*/
public func scrollToPreviousViewController()
if let visibleViewController = viewControllers?.last,
let previousViewController = pageViewController(self, viewControllerBefore: visibleViewController)
scrollToViewController(viewController: previousViewController, direction: .reverse)
/**
Scrolls to the view controller at the given index. Automatically calculates
the direction.
- parameter newIndex: the new index to scroll to
*/
func scrollToViewController(index newIndex: Int)
if let firstViewController = viewControllers?.first,
let currentIndex = getViewsList().index(of:firstViewController)
let direction: UIPageViewControllerNavigationDirection = newIndex >= currentIndex ? .forward : .reverse
let nextViewController = getViewsList()[newIndex]
scrollToViewController(viewController:nextViewController, direction: direction)
/**
Scrolls to the given 'viewController' page.
- parameter viewController: the view controller to show.
*/
private func scrollToViewController(viewController: UIViewController,
direction: UIPageViewControllerNavigationDirection = .forward)
setViewControllers([viewController],
direction: direction,
animated: true,
completion: (finished) -> Void in
// Setting the view controller programmatically does not fire
// any delegate methods, so we have to manually notify the
// 'tutorialDelegate' of the new index.
self.notifyHomePageDelegateOfNewIndex()
self.lastShownControl = viewController as? PageContainerViewController
self.showTutorial()
)
/**
Notifies '_tutorialDelegate' that the current page index was updated.
*/
private func notifyHomePageDelegateOfNewIndex()
if let firstViewController = viewControllers?.first,
let index = getViewsList().index(of:firstViewController)
homePageDelegate?.homePageViewController(homePageViewController: self, didUpdatePageIndex: index)
// MARK: UIPageViewControllerDataSource
extension HomePageViewController: UIPageViewControllerDataSource
func pageViewController(_ pageViewController: UIPageViewController,
viewControllerBefore viewController: UIViewController) -> UIViewController?
guard let viewControllerIndex = getViewsList().index(of:viewController) else
return nil
let previousIndex = viewControllerIndex - 1
// User is on the first view controller and swiped left to loop to
// the last view controller.
guard previousIndex >= 0 else
return nil
guard getViewsList().count > previousIndex else
return nil
return getViewsList()[previousIndex]
func pageViewController(_ pageViewController: UIPageViewController,
viewControllerAfter viewController: UIViewController) -> UIViewController?
guard let viewControllerIndex = getViewsList().index(of:viewController) else
return nil
let nextIndex = viewControllerIndex + 1
let listViewControllersCount = getViewsList().count
// User is on the last view controller and swiped right to loop to
// the first view controller.
guard listViewControllersCount != nextIndex else
return nil
guard listViewControllersCount > nextIndex else
return nil
return getViewsList()[nextIndex]
//MARK: - WebSocket Delegat
func connectionPartnerChanged(success: Bool)
partnerConnectionChanged = true
extension HomePageViewController: UIPageViewControllerDelegate
func pageViewController(_ pageViewController: UIPageViewController,
didFinishAnimating finished: Bool,
previousViewControllers: [UIViewController],
transitionCompleted completed: Bool)
notifyHomePageDelegateOfNewIndex()
protocol HomePageViewControllerDelegate: class
/**
Called when the number of pages is updated.
- parameter homePageViewController: the TutorialPageViewController instance
- parameter count: the total number of pages.
*/
func homePageViewController(homePageViewController: HomePageViewController,
didUpdatePageCount count: Int)
/**
Called when the current index is updated.
- parameter homePageViewController: the TutorialPageViewController instance
- parameter index: the index of the currently visible page.
*/
func homePageViewController(homePageViewController: HomePageViewController,
didUpdatePageIndex index: Int)
【问题讨论】:
嗯?快速测试,viewWillAppear()
和 viewDidAppear()
在 UIPageViewController
中的视图控制器之间滑动(滚动)时都会触发。您确定将代码放在正确的位置吗?
我不知道为什么,但我的没有被调用,因为我通过调试对其进行了测试。我添加了我的 UIPageViewController 代码,以便您在发现任何错误时告诉我。
viewWillAppear
从未被调用过或被调用过一次,我认为它至少被调用过一次。
viewWillAppear
每次您导航或返回同一屏幕时都会调用。在您的情况下,UIPageViewController
就像 rootViewController
,它不是在滑动时导航,但您的 UIViewController
正在导航.
@danypata 它在第一次显示时被调用,但之后当我滑动时它就不会被调用。
【参考方案1】:
使用这个UIPageViewController Delegate method
:
func pageViewController(_ pageViewController: UIPageViewController,
willTransitionTo pendingViewControllers: [UIViewController])
let controller = pendingViewControllers?.first as? SecondViewController
func pageViewController(_ pageViewController: UIPageViewController,
didFinishAnimating finished: Bool,
previousViewControllers: [UIViewController],
transitionCompleted completed: Bool)
if completed
【讨论】:
【参考方案2】:viewWillAppear
和 viewDidAppear
为出现的视图控制器调用。
因此,您需要在“页面”视图控制器中实现这些功能 ... 而不是在UIPageViewController
本身内。
如果您需要UIPageViewController
了解它,请实现willTransitionTo
和didFinishAnimating
UIPageViewController 委托方法,或创建您自己的协议/委托函数。
【讨论】:
我确实在UIViewController
中添加了viewDidAppear
,但有时它没有被调用。尤其是当您在页面之间滑动时。
我必须实现一个要遵守的协议,这样我才能使用 UIPageViewControllerDelegate 方法在细节 VC 上调用一个方法。这让您知道 VC 现在是可见的,以便 VC 可以刷新其状态。注意:pageVIewController:willTransitionTo:
方法可以在用户向其他方向滑动时被取消,因此您需要检查pageViewController:didFinishAnimating:previousViewControllers:completed
中的completed
标志以确保它实际转换(否则活动视图可能是previousVC) .以上是关于viewWillAppear 没有在 UIPageViewController 孩子上被调用的主要内容,如果未能解决你的问题,请参考以下文章
Xcode:Navigationcontroller 加载 UIpage 控制的视图?
在 UITableViewController 中没有调用 viewWillAppear?
popviewcontroller 没有调用 viewWillappear