我有一个PageViewController, P ,其中包含两个子ViewController, A 和 B 。 A 和 B 都允许用户在表单中输入一些数据。如果用户开始编辑表单,我将跟踪一个布尔变量:
var formEdited = false;
如果用户想离开表单,并且formEdited为true,我想警告他们并说:“您确定要放弃表单中的更改吗?”。如果他们确定,我想存储他们的数据。否则,我会让他们丢弃数据并继续刷卡。
结果,我尝试在 A 和 B 中执行以下操作:
override func viewWillDisappear(_ animated: Bool) {
if (formEdited) {
let dialogMessage = UIAlertController(title: "Confirm", message: "Are you sure you want to abandon the changes you have in the form?", preferredStyle: .alert);
let ok = UIAlertAction(title: "OK", style: .default, handler: { (action) -> Void in
super.viewWillDisappear(animated);
})
let cancel = UIAlertAction(title: "Cancel", style: .cancel) { (action) -> Void in
// TODO:: what to do here
self.myCustomFuctionToStoreData();
super.viewWillAppear(true);
}
dialogMessage.addAction(ok);
dialogMessage.addAction(cancel);
self.present(dialogMessage, animated: true, completion: nil);
}
}
结果是,当我尝试从“视图”滑开时,我可以看到我的弹出窗口。如果单击“取消”,则视图仍然存在。 (这是我想要的)但是,如果我再次尝试再次滑动,将不再看到警报框,并且UI也会更改。 (这不是我想要的。我希望它再次提示)
我认为当viewWillDisappear出现时,我的代码需要做出更适当的反应。我想我需要以某种方式防止视图在上面的这一行之后消失:
// TODO:: what to do here
注意:我已经尝试了其他一些帖子的答案,例如:How do I Disable the swipe gesture of UIPageViewController?,Disable swipe gesture in UIPageViewController,甚至是这两个帖子:Disable UIPageViewController Swipe - Swift和Checking if a UIViewController is about to get Popped from a navigation stack?。
最后两个可能是最合适的,但是我不想禁用任何手势,也不想看到如何注入预防措施。我只是想使从子视图的滑动成为条件函数。如何在Swift 4的子视图(PageView的子视图)中做到这一点?
答案 0 :(得分:0)
事实证明,在UIPageView中实现条件滚动操作是微不足道的。这些是我为解决问题所采取的步骤。 (鼓励对此代码进行更新以使其更高效)
对于初学者,您的UIPageViewController不得为dataSource。这意味着在子视图控制器中进行滚动操作时,不会进行任何注册。 (现在可以了)相反,您希望实现逻辑,以便在子视图可以调用的函数时显示视图。可以将这两种方法添加到您的UIPageView中:
func goToNextView(currentViewController : UIViewController) {
var movingIdx = 0;
let viewControllerIndex = orderedViewControllers.index(of: currentViewController) ?? 0;
if (viewControllerIndex + 1 <= (orderedViewControllers.count - 1)) {
movingIdx = viewControllerIndex + 1;
}
self.setViewControllers([orderedViewControllers[movingIdx]], direction: .forward, animated: true, completion: nil);
}
func goToPreviousView(currentViewController : UIViewController) {
var movingIdx = 0;
let viewControllerIndex = orderedViewControllers.index(of: currentViewController) ?? -1;
if (viewControllerIndex == -1) {
movingIdx = 0;
} else if (viewControllerIndex - 1 >= 0) {
movingIdx = viewControllerIndex - 1;
} else {
movingIdx = orderedViewControllers.count - 1;
}
self.setViewControllers([orderedViewControllers[movingIdx]], direction: .reverse, animated: true, completion: nil);
}
注意:
更新包含??的行是有意义的0;引发错误或显示某些默认屏幕的方式。
orderedViewControllers是此UIPageView控制器包含的所有子视图的列表
这些方法将从子视图中调用,因此将它们保留在这一层将使其非常可重用
最后,在子视图中,您需要一种识别手势并对手势做出反应的方法:
override func viewDidLoad() {
super.viewDidLoad();
let swipeLeft = UISwipeGestureRecognizer(target: self, action: #selector(handleGesture))
swipeLeft.direction = .left
self.view.addGestureRecognizer(swipeLeft)
let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(handleGesture))
swipeRight.direction = .right
self.view.addGestureRecognizer(swipeRight)
}
处理手势:
@objc func handleGesture(gesture: UISwipeGestureRecognizer) -> Void {
if gesture.direction == UISwipeGestureRecognizerDirection.left {
parentPageViewController.goToNextView(currentViewController: self);
}
else if gesture.direction == UISwipeGestureRecognizerDirection.right {
parentPageViewController.goToPreviousView(currentViewController: self);
}
}
注意:
在handleGesture函数中,您将添加条件检查以确定goToNextView或goToPreviousView是否可以。