Swift iOS:如何使用button触发下一页
我有一个QuizViewController它扩展了UIViewController , UIPageControllerDelegate
和一个UIPageViewControllerDataSource
。
里面QuizViewController.swift
private var pageViewController: UIPageViewController? private func createPageViewController() { let pageController = self.storyboard!.instantiateViewControllerWithIdentifier("QuizPageViewController") as! UIPageViewController pageController.dataSource = self if pageInfo.count > 0 { let firstController = getItemController(0)! let startingViewControllers: NSArray = [firstController] pageController.setViewControllers(startingViewControllers as? [UIViewController], direction: UIPageViewControllerNavigationDirection.Forward, animated: false, completion: nil) } pageViewController = pageController addChildViewController(pageViewController!) self.view.addSubview(pageViewController!.view) pageViewController!.didMoveToParentViewController(self) } private func getItemController(itemIndex: Int) -> QuizPageItem? { if itemIndex < pageInfo.count { let CurrentQuizPageItem = self.storyboard!.instantiateViewControllerWithIdentifier("QuizPageItem") as! QuizPageItem CurrentQuizPageItem.itemIndex = itemIndex CurrentQuizPageItem.thisPageInfo = pageInfo[itemIndex] return CurrentQuizPageItem } return nil } /* PageView Delegates */ func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? { let CurrentQuizPageItem = viewController as! QuizPageItem if CurrentQuizPageItem.itemIndex > 0 { return getItemController(CurrentQuizPageItem.itemIndex - 1) } return nil } func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? { let CurrentQuizPageItem = viewController as! QuizPageItem if CurrentQuizPageItem.itemIndex + 1 < pageInfo.count { return getItemController(CurrentQuizPageItem.itemIndex + 1) } return nil }
我的问题是如何让下一个和后退button正常工作?
现在可以通过刷卡来改变页面。 我不想使用滑动。 我想控制使用下一个和后退button。
UPDATE
这是在Main.storyboard上
PageViewController是故事板中的中间一个。
PageViewController具有作为QuizPageViewController的故事板ID。
QuizViewController是故事板中的左侧。
QuizViewController使用故事板ID QuizPageViewController实例化一个PageViewController
这是由这个块完成的
let pageController = self.storyboard!.instantiateViewControllerWithIdentifier("QuizPageViewController") as! UIPageViewController pageController.dataSource = self
当这个实例化发生时,它也创build了QuizPageItem的首页。
QuizPageItem是Main.storyboard中最正确的视图。
所以如果你看到2个模型,它们都是QuizPageItems。
第一个模型应该有一个itemIndex为0。
第二个模型应该有1的itemIndex。
let CurrentQuizPageItem = self.storyboard!.instantiateViewControllerWithIdentifier("QuizPageItem") as! QuizPageItem CurrentQuizPageItem.itemIndex = itemIndex
我收到的大部分答案都build议通过QuizViewController (也就是我的Main.storyboard中最左边的视图)来解决它。
但是,这些button位于QuizPageItem中,无法通过QuizViewController进行访问。
我想知道如何连接QuizPageItem中的后退/下一步button来执行QuizViewController中控制的分页, 假定我将Main.storyboard中的各种视图连接起来的方式是正确的
同时,我允许目前我接线Main.storyboard中各种视图的方式并不理想。
如果是这样,请告诉另一种方法。
这是我遵循的教程去到我目前在哪里。
http://shrikar.com/ios-swift-tutorial-uipageviewcontroller-as-user-onboarding-tool/
更新2我很抱歉,我被视为争论。 我真的想学习如何做到这一点。 我很确定我缺乏一些基础知识,因此我无法理解Michael Dautermann的答案。
我猜测QuizViewController中有一个函数会触发翻页。
我不确定这个function是什么。
这些是我知道的button被按下时触发的function。
QuizPageItem类中有以下内容
@IBAction func pageBackButton(sender: AnyObject) { } @IBAction func pageNextButton(sender: AnyObject) { }
但是,它们不在QuizViewController类中,而是在QuizPageItem类中。
我应该把setViewController方法在QuizPageItem类中的这两个函数?
如果是的话,我怎样才能从QuizPageItem类中访问QuizViewController实例?
更新3:
我的文件结构是
- QuizViewController.swift
- QuizPageItem.swift
QuizViewController控制你看到的QuizPageItem。 QuizPageItem表示由模型devise的不同视图。
UPDATE4:
马特的回答帮助我了解了这个我完全不熟悉的FirstResponder。
当我试图执行它时,我遇到了这个错误。
我search了一下,我试图补救它无济于事。
我一直触发这个错误。
附件是QuizViewPageItemController.swift
的代码片段
import UIKit class QuizPageItemViewController: UIViewController, CheckboxDelegate { @IBOutlet weak var pageHeadingLabel: UILabel! @IBOutlet weak var pageInstructionLabel: UILabel! @IBOutlet weak var pageProgressView: UIProgressView! @IBOutlet weak var pageQuestionLabel: UILabel! @IBOutlet weak var pageAnswerView: UIView! @IBOutlet weak var pageBackButton: UIButton! @IBOutlet weak var pageNextButton: UIButton! let pageNo: Int let maxPageNo: Int let thisPageInfo: [String] let interestsList = [ "Blue Chips", "Small Caps", "Pharmaceuticals", "Agriculture", "Telecommunications", "Manufacturing", "Finance", "Banks", "Retail", "Travel", "Airlines", "Tourism"] init(pageNo: Int, maxPageNo: Int, thisPageInfo: [String]) { self.pageNo = pageNo self.maxPageNo = maxPageNo self.thisPageInfo = thisPageInfo super.init(nibName: nil, bundle: nil) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func viewDidLoad() { super.viewDidLoad() self.pageBackButton.hidden = pageNo == 0 self.pageNextButton.hidden = pageNo == maxPageNo pageHeadingLabel.text = thisPageInfo[0] pageInstructionLabel.text = thisPageInfo[1] pageQuestionLabel.text = thisPageInfo[2] if thisPageInfo[0] == "Welcome" { createCheckboxes() pageProgressView.setProgress(0.33, animated: true) } else if thisPageInfo[0] == "Awesome!" { createSlider() pageProgressView.setProgress(0.67, animated: true) } else if thisPageInfo[0] == "Almost there..." { createSlider() pageProgressView.setProgress(0.95, animated: true) } } override func viewDidAppear(animated: Bool) { super.viewDidAppear(animated) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } func createCheckboxes() { let fWidth = (self.view.frame.width - 40) / 2 var frame = CGRectMake(0, 0, fWidth, 40) var contentSize = CGRectMake(0, 0, self.view.frame.width - 40, 0) for (var counter = 0; counter < interestsList.count; counter++) { let checkbox = Checkbox(frame: frame, title: interestsList[counter], selected: false) checkbox.mDelegate = self checkbox.tag = counter checkbox.backgroundColor = UIColor.redColor() if counter % 2 == 0 { frame.origin.x += fWidth } else{ frame.origin.x -= fWidth frame.origin.y += frame.size.height contentSize.size.height += frame.size.height } checkbox.titleLabel?.adjustsFontSizeToFitWidth = true pageAnswerView.addSubview(checkbox) } } func didSelectCheckbox(state: Bool, identifier: Int, title: String) { print("checkbox '\(title)' has state \(state)") } func createSlider() { let slider = UISlider(frame:CGRectMake(0, 20, self.view.frame.width - 40, 20)) slider.minimumValue = 0 slider.maximumValue = 10 slider.continuous = true slider.tintColor = ChatQColours().chatQBlue slider.value = 5 // slider.addTarget(self, action: "sliderValueDidChange:", forControlEvents: .ValueChanged) pageAnswerView.addSubview(slider) let leftlabel = UILabel(frame: CGRectMake(0, 40, 0, 0)) leftlabel.text = "Strongly Avoid" leftlabel.sizeToFit() pageAnswerView.addSubview(leftlabel) let rightlabel = UILabel(frame: CGRectMake(0, 40, 0, 0)) rightlabel.text = "Strongly Prefer" rightlabel.sizeToFit() rightlabel.frame.origin.x = slider.frame.width - rightlabel.frame.width pageAnswerView.addSubview(rightlabel) } }
你(OP)需要多听,less争论。 Michael Dautermann的回答是完全正确的,因为这个截屏显示:
你看到的是一个页面视图控制器有多个页面(编号,所以你可以看到订单),每个页面包含一个下一步button,我反复按下一步button导航到下一页。
像你的,我的项目,在上面的屏幕截图中有说明,有一个视图控制器层次结构:
-
的UITabBarController
-
视图控制器
-
UIPageViewController
-
页面(有主视图,标签和button是子视图)
看起来问题的核心不是什么方法导致页面视图控制器导航到其下一页或上一页 – 正如你已经被告知,只是setViewControllers:...
– 但如何button通信在视图控制器层次结构。 在我的例子中,这意味着从页面视图中的button发送消息,通过页面视图控制器,通过UIPageViewController,然后到ViewController,然后告诉UIPageViewController做什么。
我可以想到很多方法来做到这一点:
-
该button发布ViewController注册的通知
-
该button发送一个无针对的行动,ViewController有一个处理程序
-
该button将消息发送到标签栏控制器(它的
tabBarController
属性),然后将消息发送到其当前选定的视图控制器,ViewController -
该button向其视图控制器(在笔尖或故事板中configuration为动作)发送消息,该消息向
parentViewController!.parentViewController!
视图控制器parentViewController!.parentViewController!
发送消息parentViewController!.parentViewController!
,这是ViewController。
我更喜欢哪个? 就我个人而言,我最喜欢无目标行为,因为它不需要额外的代码。 唯一的func pageNextButton()
实现在ViewController中。 这是一个没有针对性的行动的美:它自动走向响应者链,寻找接收者。 页面视图控制器和UIPageViewController在这方面根本没有代码。
我喜欢这比parentViewController!.parentViewController!
更好parentViewController!.parentViewController!
,因为后者最终要求页面视图控制器知道它可以调用的ViewController中的方法的名称,并且它必须强制转换为ViewController – 这不是非常便于使用,并且给页面视图控制器太多的知识环境,在我看来。 另一方面,以零为目标的行动,发件人完全不知道实际的目标会是谁! 所以我最喜欢零目标行动,通知次好。
Swift 3.0
这里非常简单的解决scheme
要从UIViewController更改页面(UIViewController),首先获取父视图控制器(这将是UIPageViewController)的实例,然后设置其当前ViewController
在我的情况下,我有一个名为“UserDetailsPVC”的UIPageViewController,它包含4页(UIViewControllers),如下所示
PageOneVC:UIViewController PageTwoVC:UIViewController PageThreeVC:UIViewController PageFourVC:UIViewController
在UIPageViewController中可以定义一个页面数组
var pages:[UIViewController] = [ UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "PageOneVC"), UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "PageTwoVC"), UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "PageThreeVC"), UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "PageFourVC") ]
现在从任何UIViewController更改UIPageViewController的页面
// get parent view controller let parentVC = self.parent as! UserDetailsPVC // change page of PageViewController parentVC.setViewControllers([parentVC.pages[1]], direction: .forward, animated: true, completion: nil)
您可以使用setViewControllers:direction:animated:completion:
以编程方式打开您的页面 。
只要通过前一页或下一页的视图控制器,你应该全部设置。
您可以使用:
下一页
pageViewController.setViewControllers(startingViewControllers, direction: UIPageViewControllerNavigationDirection.Forward, animated: true, completion: nil)
对于前一页
pageViewController.setViewControllers(startingViewControllers, direction: UIPageViewControllerNavigationDirection.Reverse, animated: true, completion: nil)
你可以使用这个function:
func movePageToIndex(pageIndex NSInteger)->() { var viewControllers = [] var direction : UIPageViewControllerNavigationDirection! if (pageIndex < currentIndex) { direction = UIPageViewControllerNavigationDirection.Reverse } else { direction = UIPageViewControllerNavigationDirection.Forward } viewControllers = @[[self.getItemController(pageIndex)]] WEAKSELF weakSelf = self; self.pageViewController.setViewControllers:viewControllers direction:direction animated:false completion:nil];
}