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
}
私の質問は、次へと戻るボタンを正しく機能させるにはどうすればよいですか?
現在、ページはスワイプで変更できます。スワイプは使いたくない。次へと戻るボタンを使ってコントロールしたい。
[〜#〜]更新[〜#〜]
これはMain.storyboardにあります
PageViewControllerは、ストーリーボードの真ん中のものです。
PageViewControllerのストーリーボードIDはQuizPageViewControllerです。
QuizViewControllerは、ストーリーボードの左側にあります。
QuizViewControllerは、ストーリーボードIDQuizPageViewControllerを使用してPageViewControllerをインスタンス化します。
これはこのブロックによって行われます
let pageController = self.storyboard!.instantiateViewControllerWithIdentifier("QuizPageViewController") as! UIPageViewController
pageController.dataSource = self
このインスタンス化が発生すると、QuizPageItemのフロントページも作成されます。
QuizPageItemは、Main.storyboardの右端のビューです。
したがって、2つのモックアップが表示されている場合、それらは両方ともQuizPageItemsです。
最初のモックアップのitemIndexは0である必要があります。
2番目のモックアップのitemIndexは1である必要があります。
let CurrentQuizPageItem = self.storyboard!.instantiateViewControllerWithIdentifier("QuizPageItem") as! QuizPageItem
CurrentQuizPageItem.itemIndex = itemIndex
私が受け取った回答のほとんどは、QuizViewController、つまりMain.storyboardの左端のビューを介して解決することを提案しています。
ただし、ボタンはQuizPageItemにあり、QuizViewControllerからアクセスすることはできません。
Main.storyboardのさまざまなビューを配線する方法が正しいと仮定して、QuizPageItemの[戻る]/[次へ]ボタンを接続して、QuizViewControllerで制御されるページネーションを実行する方法を知りたい
同時に、Main.storyboardのさまざまなビューを配線している現在の方法が理想的ではない可能性を許容します。
もしそうなら、別の方法をアドバイスしてください。
これは、私が現在いる場所にたどり着くために従うチュートリアルです。
http://shrikar.com/ios-Swift-tutorial-uipageviewcontroller-as-user-onboarding-tool/
UPDATE 2私は主張していると見られていることをお詫びします。私は本当にこれを行う方法を学びたいです。私はいくつかの基本的な知識が不足していると確信しているので、マイケル・ドーターマンの答えを理解することができません。
QuizViewControllerには、ページめくりをトリガーする関数があると思います。
その機能が何なのかわかりません。
これらは、ボタンが押されたときにトリガーされると私が知っている関数です。
QuizPageItemクラス内に次のものがあります
@IBAction func pageBackButton(sender: AnyObject) {
}
@IBAction func pageNextButton(sender: AnyObject) {
}
ただし、これらはQuizViewControllerクラスではなく、QuizPageItemクラスにあります。
QuizPageItemクラス内のこれら2つの関数にsetViewControllerメソッドを配置することになっていますか?
もしそうなら、QuizPageItemクラス内からQuizViewControllerインスタンスにアクセスするにはどうすればよいですか?
更新3:
私のファイル構造は
QuizViewControllerは、表示するQuizPageItemを制御します。 QuizPageItemは、モックアップによって設計された別のビューを表します。
UPDATE4:
マットの答えは、私が最初からまったくなじみのないこのFirstResponderを理解するのに大いに役立ちました。
それを実装しようとすると、このエラーに直面しました。
私はグーグルで回り、それを改善しようとしましたが無駄になりました。
私はこのエラーを引き起こし続けました。
添付されているのは、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)
}
}
このスクリーンキャストが示すように、MichaelDautermannの答えは完全に正しいです。
表示されているのは、複数のページ(順序を確認できるように番号が付けられています)があり、各ページに[次へ]ボタンが含まれているページビューコントローラーです。次のページに移動するために[次へ]ボタンを繰り返し押しています。
あなたのプロジェクトと同様に、上のスクリーンキャストに示されている私のプロジェクトには、ViewController階層があります。
UITabBarController
ViewController
UIPageViewController
ページ(メインビューがあり、ラベルとボタンはそのサブビューです)
あなたの質問の核心は、ページビューコントローラーが次または前のページに移動する方法ではなく、すでに言われているように、単に_setViewControllers:...
_ですが、ボタンがどのように通信するかということではないようです。ビューコントローラ階層を上に移動します。私の例では、これは、ページビュー内のボタンから、ページビューコントローラーを通過し、UIPageViewControllerを通過し、ViewControllerまでメッセージを送信することを意味します。ViewControllerは、UIPageViewControllerに何をすべきかを指示します。
私はそれを行うための多くの方法を考えることができます:
ボタンは、ViewControllerが登録されている通知を投稿します
ボタンは、ViewControllerがハンドラーを持っているnil-targetedアクションを送信します
ボタンはタブバーコントローラー(そのtabBarController
プロパティ)にメッセージを送信し、タブバーコントローラーは現在選択されているビューにメッセージdownを送信しますコントローラー、ViewController
ボタンは、View Controller(ペン先またはストーリーボードでアクションとして構成されている)にメッセージを送信し、View Controllerである_parentViewController!.parentViewController!
_にメッセージを送信します。
どちらが好きですか?個人的には、追加のコードを必要としないため、nil-targetedアクションが最も好きです。唯一のfunc pageNextButton()
実装はViewControllerにあります。これは、ターゲットを絞らないアクションの美しさです。レスポンダーチェーンをたどり、受信者を探します自動的に。ページビューコントローラーとUIPageViewControllerには、この点に関するコードはまったくありません。
私はこれが_parentViewController!.parentViewController!
_よりもはるかに好きです。後者は最終的にPage View Controllerが呼び出すことができるViewControllerのメソッドの名前を知っている必要があり、ViewControllerにキャストダウンする必要があるためです。これはあまり移植性がありません。私の意見では、ページビューコントローラにその環境についての知識が多すぎます。一方、ターゲットを絞らないアクションでは、送信者は実際のターゲットが誰であるかについて完全に不可知論者です。だから私はnil-targetアクションが一番好きで、通知が2番目に好きです。
Swift 3.
非常に簡単な解決策はここにあります
UIViewControllerからページ(UIViewController)を変更するには、最初に親ViewControllerのインスタンス(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")
]
次に、UIPageViewControllerのページを任意のUIViewControllerから変更します
// 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:
から プログラムでページをめくる 。
前または次のページのViewControllerを渡すだけで、すべての設定が完了します。
次を使用できます。
次のページ
pageViewController.setViewControllers(startingViewControllers,
direction: UIPageViewControllerNavigationDirection.Forward,
animated: true,
completion: nil)
前のページ
pageViewController.setViewControllers(startingViewControllers,
direction: UIPageViewControllerNavigationDirection.Reverse,
animated: true,
completion: nil)
この機能を使用できます:
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];
}
Swift4.2あなたの望みを動かす非常に簡単な方法ViewController
//MARK:- Programatically move to Next Page or Previous Page
//Your Desire index in Your UIViewController Array
let arr : [UIViewController] = [arrvc[1]]
pagecontroller.setViewControllers(arr,
direction: UIPageViewController.NavigationDirection.reverse,
animated: true,
completion: nil)