私は3つのメインビューを持つアプリを開発しています。ユーザーがスワイプするだけで3つのビューを変更できるようにするために(Tinderアプリのように)、PageViewControllerを作成しました。これはうまく機能します。このPageViewControllerは次のように機能します。
また、各3つのビューの上部にボタンを追加し、ユーザーがそれらのビューをスワイプしたときと同じように、それらのボタンをタップして他のビューにスライドできるようにしました(これもTinderのようなものです)。
そこで、実験のために、SecondViewControllerに2つのボタンを追加しました。左はFirstViewControllerに移動するためのもので、右はThirdViewControllerに移動するためのものです。次に、SecondViewControllerファイルに「UIPageViewControllerDelegate」を追加し、PageViewControllerファイルから左ボタンの「getFirst」メソッドと右ボタンの「getThird」メソッドを呼び出そうとしました。
しかし、左ボタンをタップすると、PageViewControllerファイルの「getFirst」メソッド行にこのエラーメッセージが表示されます(右ボタンでも同じエラーが発生する可能性があります)。
スレッド1:致命的なエラー:オプション値のアンラップ中に予期せずnilが見つかりました
コードは以下のとおりです。
PageViewController
import UIKit
class PageViewController: UIPageViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.setViewControllers([getFirst()], direction: .forward, animated: true, completion: nil)
self.dataSource = self as UIPageViewControllerDataSource
}
}
extension PageViewController : UIPageViewControllerDataSource {
//FirstViewController
@objc func getFirst() -> FirstViewController {
return storyboard!.instantiateViewController(withIdentifier: "FirstViewController") as! FirstViewController
}
//SecondViewController
@objc func getSecond() -> SecondViewController {
return storyboard!.instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController
}
//ThirdViewController
@objc func getThird() -> ThirdViewController {
return storyboard!.instantiateViewController(withIdentifier: "ThirdViewController") as! ThirdViewController
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
if viewController.isKind(of: ThirdViewController.self) {
// 3 -> 2
return getSecond()
} else if viewController.isKind(of: SecondViewController.self) {
// 2 -> 1
return getFirst()
} else {
// 1 -> end of the road
return nil
}
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
if viewController.isKind(of: FirstViewController.self) {
// 1 -> 2
return getSecond()
} else if viewController.isKind(of: SecondViewController.self) {
// 2 -> 3
return getThird()
} else {
// 3 -> end of the road
return nil
}
}
}
SecondViewController
import UIKit
class SecondViewController: UIViewController, UIPageViewControllerDelegate {
let pageHelper = PageViewController()
override func viewDidLoad() {
super.viewDidLoad()
pageHelper.delegate = self
}
@IBAction func toFirstTapped(_ sender: Any) {
pageHelper.getFirst()
}
}
何が足りないの?たぶん私はそれをこのように機能させることができません(他のファイルからPageViewControllerを再利用することはできませんか?)。
誰か助けてくれませんか!
まず、PageViewController
インスタンス化する子コントローラーをインスタンス化しPageViewController
ます..それは本当に良い考えですか?次に、で、toFirstTapped
インスタンス化しますが、FirstViewController
何もしません。
あなたがそれで何もしない場合、あなたはそれがどのように機能することを期待しますか?
いずれにせよ、以下を試してください。
protocol PageNavigationDelegate : class {
weak var pageController: PageViewController? { get set }
}
class PageViewController: UIPageViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.setViewControllers([getFirst()], direction: .forward, animated: true, completion: nil)
self.dataSource = self as UIPageViewControllerDataSource
}
}
extension PageViewController : UIPageViewControllerDataSource {
func getFirst() -> FirstViewController {
let controller = storyboard!.instantiateViewController(withIdentifier: "FirstViewController") as! FirstViewController
controller.pageController = self
return controller
}
func getSecond() -> SecondViewController {
let controller = storyboard!.instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController
controller.pageController = self
return controller
}
func getThird() -> ThirdViewController {
let controller = storyboard!.instantiateViewController(withIdentifier: "ThirdViewController") as! ThirdViewController
controller.pageController = self
return controller
}
@discardableResult
func goToPreviousPage() -> Bool {
let controller = self.viewControllers!.first!
if controller.isKind(of: SecondViewController.self) {
self.setViewControllers([getFirst()], direction: .reverse, animated: true, completion: nil)
return true
}
if controller.isKind(of: ThirdViewController.self) {
self.setViewControllers([getSecond()], direction: .reverse, animated: true, completion: nil)
return true
}
return false
}
@discardableResult
func goToNextPage() -> Bool {
let controller = self.viewControllers!.first!
if controller.isKind(of: FirstViewController.self) {
self.setViewControllers([getSecond()], direction: .forward, animated: true, completion: nil)
return true
}
if controller.isKind(of: SecondViewController.self) {
self.setViewControllers([getThird()], direction: .forward, animated: true, completion: nil)
return true
}
return false
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
if viewController.isKind(of: SecondViewController.self) {
return getFirst()
}
if viewController.isKind(of: ThirdViewController.self) {
return getSecond()
}
return nil
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
if viewController.isKind(of: FirstViewController.self) {
return getSecond()
}
if viewController.isKind(of: SecondViewController.self) {
return getThird()
}
return nil
}
}
class PageNavigationController : UIViewController, PageNavigationDelegate {
var pageController: PageViewController?
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func goToPreviousController(_ sender: Any) {
pageController?.goToPreviousPage()
}
@IBAction func goToNextController(_ sender: Any) {
pageController?.goToNextPage()
}
}
class FirstViewController: PageNavigationController {
}
class SecondViewController: PageNavigationController {
}
class ThirdViewController: PageNavigationController {
}
まず、プロトコルを作成しました。PageControllerのすべてのサブコントローラーがそれを実装することを確認しました。このようにして、前のページと次のページに移動できます。
次に、goToPreviousPage
andgoToNextPage
関数を持つ拡張機能を作成します。各コントローラーページをインスタンス化するときにself
、そのプロトコル実装変数に割り当てます。このようにして、コントローラーはPageViewController
のメソッドにアクセスできます。
最後に、私たちの中でFirst
、Second
、およびThird
コントローラ、私たちは、ボタンを押す上の前方または後方に行くためにそれを伝えます。
個人的には、配列内のコントローラーを追跡し、それらをデリゲートに返すことを好みます。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加