Swift: UIPageViewController - загрузка отдельных представлений
Я следую этому руководству: http://swiftiostutorials.com/ios-tutorial-using-uipageviewcontroller-create-content-slider-objective-cswift/, чтобы создать приложение с несколькими ползунками.
Несмотря на то, что у меня есть этот учебник для работы, этот пример изменяет только изображение, основанное на тех, которые хранятся в массиве.
Как я могу получить его для загрузки ViewControllers вместо изображений
У меня есть 4 ViewControllers:
- ViewController1
- ViewController2
- ViewController3
- ViewController4
Я хотел бы сместить один, чтобы показать ViewController1 и slide2, чтобы загрузить ViewController2 и т.д.
Вот мой основной ViewController:
import UIKit
class ViewController: UIViewController, UIPageViewControllerDataSource {
// MARK: - Variables
private var pageViewController: UIPageViewController?
// Initialize it right away here
private let contentImages = ["nature_pic_1.png",
"nature_pic_2.png",
"nature_pic_3.png",
"nature_pic_4.png"];
// MARK: - View Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
createPageViewController()
setupPageControl()
}
private func createPageViewController() {
let pageController = self.storyboard!.instantiateViewControllerWithIdentifier("PageController") as UIPageViewController
pageController.dataSource = self
if contentImages.count > 0 {
let firstController = getItemController(0)!
let startingViewControllers: NSArray = [firstController]
pageController.setViewControllers(startingViewControllers, direction: UIPageViewControllerNavigationDirection.Forward, animated: false, completion: nil)
}
pageViewController = pageController
addChildViewController(pageViewController!)
self.view.addSubview(pageViewController!.view)
pageViewController!.didMoveToParentViewController(self)
}
private func setupPageControl() {
let appearance = UIPageControl.appearance()
appearance.pageIndicatorTintColor = UIColor.grayColor()
appearance.currentPageIndicatorTintColor = UIColor.whiteColor()
appearance.backgroundColor = UIColor.darkGrayColor()
}
// MARK: - UIPageViewControllerDataSource
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
let itemController = viewController as PageItemController
if itemController.itemIndex > 0 {
return getItemController(itemController.itemIndex-1)
}
return nil
}
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
let itemController = viewController as PageItemController
if itemController.itemIndex+1 < contentImages.count {
return getItemController(itemController.itemIndex+1)
}
return nil
}
private func getItemController(itemIndex: Int) -> PageItemController? {
if itemIndex < contentImages.count {
let pageItemController = self.storyboard!.instantiateViewControllerWithIdentifier("ItemController") as PageItemController
pageItemController.itemIndex = itemIndex
pageItemController.imageName = contentImages[itemIndex]
return pageItemController
}
return nil
}
// MARK: - Page Indicator
func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int {
return contentImages.count
}
func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int {
return 0
}
и вот мой параметр PageItemController:
import UIKit
class PageItemController: UIViewController {
// MARK: - Variables
var itemIndex: Int = 0
var imageName: String = "" {
didSet {
if let imageView = contentImageView {
imageView.image = UIImage(named: imageName)
}
}
}
@IBOutlet var contentImageView: UIImageView?
// MARK: - View Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
contentImageView!.image = UIImage(named: imageName)
}
}
Я новичок в Swift/iOS Development и действительно пытаюсь проникнуть в нее, развиваясь. Заранее благодарю за ваши ответы:)
РЕДАКТИРОВАТЬ: очистить вопрос
Как мне сделать так, чтобы существовал массив контроллеров представлений, соответствующих слайду слева и справа от UIPageViewController?
Итак, когда я прокручиваю влево на ViewController1 - UIViewController2 загружается и обращается для прямого прокрутки.
Ответы
Ответ 1
Предполагая, что у вас есть контроллеры представления 1-4, определенные в той же раскадровке, что и ваш UIPageViewController, и у вас есть идентификаторы раскадровки, установленные как ViewController0, ViewController1 и т.д., затем создайте метод для заполнения массива контроллера вида и вызовите его ваш viewDidLoad()
перед вызовом createPageViewController()
override func viewDidLoad() {
super.viewDidLoad()
populateControllersArray()
createPageViewController()
setupPageControl()
}
Внедрите метод следующим образом:
var controllers = [PageItemController]()
func populateControllersArray() {
for i in 0...3 {
let controller = storyboard!.instantiateViewControllerWithIdentifier("ViewController\(i)") as PageItemController
controller.itemIndex = i
controllers.append(controller)
}
}
И определите свой createPageViewController()
как следующий
private func createPageViewController() {
let pageController = self.storyboard!.instantiateViewControllerWithIdentifier("PageController") as UIPageViewController
pageController.dataSource = self
if !controllers.isEmpty {
pageController.setViewControllers([controllers[0]], direction: UIPageViewControllerNavigationDirection.Forward, animated: false, completion: nil)
}
pageViewController = pageController
addChildViewController(pageViewController!)
self.view.addSubview(pageViewController!.view)
pageViewController!.didMoveToParentViewController(self)
}
то в ваших двух делегатах до и после методов:
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
if let controller = viewController as? PageItemController {
if controller.itemIndex > 0 {
return controllers[controller.itemIndex - 1]
}
}
return nil
}
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
if let controller = viewController as? PageItemController {
if controller.itemIndex < controllers.count - 1 {
return controllers[controller.itemIndex + 1]
}
}
return nil
}
И в методе count
func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int {
return controllers.count
}
Фактически вы можете заполнить controllers
любыми контроллерами представлений, которые вы хотите отобразить, просто установите их класс как PageItemController в раскадровке (чтобы иметь свойство индекса).
Или вы можете установить каждый контроллер представления как свой собственный класс и использовать свойства и настройки времени выполнения.
Используйте controller.valueForKey("itemIndex") as Int
в методах до и после вместо controller.itemIndex
Используйте controller.setValue(i, forKey: "itemIndex")
вместо controller.itemIndex = i
в populateControllersArray()
.
Просто убедитесь, что каждый класс контроллера имеет свойство Int
itemIndex
, или ваше приложение будет аварийно завершено.
Чтобы привести все это вместе в свой код, выполните следующие действия:
import UIKit
import UIKit
class ViewController: UIViewController, UIPageViewControllerDataSource {
// MARK: - Variables
private var pageViewController: UIPageViewController?
// MARK: - View Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
populateControllersArray()
createPageViewController()
setupPageControl()
}
var controllers = [PageItemController]()
func populateControllersArray() {
for i in 0...3 {
let controller = storyboard!.instantiateViewControllerWithIdentifier("ViewController\(i)") as PageItemController
controller.itemIndex = i
controllers.append(controller)
}
}
private func createPageViewController() {
let pageController = self.storyboard!.instantiateViewControllerWithIdentifier("PageController") as UIPageViewController
pageController.dataSource = self
if !controllers.isEmpty {
pageController.setViewControllers([controllers[0]], direction: UIPageViewControllerNavigationDirection.Forward, animated: false, completion: nil)
}
pageViewController = pageController
addChildViewController(pageViewController!)
self.view.addSubview(pageViewController!.view)
pageViewController!.didMoveToParentViewController(self)
}
private func setupPageControl() {
let appearance = UIPageControl.appearance()
appearance.pageIndicatorTintColor = UIColor.grayColor()
appearance.currentPageIndicatorTintColor = UIColor.whiteColor()
appearance.backgroundColor = UIColor.darkGrayColor()
}
// MARK: - UIPageViewControllerDataSource
func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
if let controller = viewController as? PageItemController {
if controller.itemIndex > 0 {
return controllers[controller.itemIndex - 1]
}
}
return nil
}
func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
if let controller = viewController as? PageItemController {
if controller.itemIndex < controllers.count - 1 {
return controllers[controller.itemIndex + 1]
}
}
return nil
}
// MARK: - Page Indicator
func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int {
return controllers.count
}
func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int {
return 0
}
Ответ 2
Вы загружаете ViewControllers для каждой страницы. каждое изображение, которое вы показываете, находится внутри собственного ViewController. Это делается через:
private func getItemController(itemIndex: Int) -> PageItemController?
если каждая ваша страница использует один и тот же макет, здесь нечего делать, кроме проектирования этого ViewController в Interface Builder.
Если, однако, каждая страница использует другой макет и показывает разные данные, вы сначала должны прототип/дизайн этих ViewControllers в Interface Builder.
то вы должны создавать классы для каждого ViewController и расширять их из PageItemController. Вы сохраняете только переменную индекса в PageItemController и переместите остальную часть вашей логики в подклассы.
import UIKit
class PageItemController: UIViewController {
// MARK: - Variables
var itemIndex: Int = 0
}
например, viewController, который содержит изображение
import UIKit
class PageImageViewController: PageItemController {
// MARK: - Outlets
@IBOutlet var contentImageView: UIImageView?
// MARK: - Variables
var imageName: String = "" {
didSet {
if let imageView = contentImageView {
imageView.image = UIImage(named: imageName)
}
}
}
// MARK: - View Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
contentImageView!.image = UIImage(named: imageName)
}
}
Наконец, вы просто измените свою функцию getItemController
, чтобы вернуть правильный ViewController для указанного индекса. здесь вы либо передаете данные в ViewController, либо просто возвращаете его.
private func getItemController(itemIndex: Int) -> UIViewController? {
var vc: PageItemController? = nil
switch itemIndex {
case 0:
// show an ImageViewController and pass data if needed
vc = self.storyboard!.instantiateViewControllerWithIdentifier("ImageController") as PageImageViewController
vc.itemIndex = itemIndex
vc.imageName = "any_image_file"
case 1:
// show any other ViewController and pass data if needed
vc = self.storyboard!.instantiateViewControllerWithIdentifier("ANY_OTHERController") as ANY_OTHERController
vc.PRESENTABLE_DATA = ANY_PRESENTABLE_DATA_SOURCE
vc.itemIndex = itemIndex
case 2:
// show any other ViewController and pass data if needed
vc = self.storyboard!.instantiateViewControllerWithIdentifier("ANY_OTHERController") as ANY_OTHERController
vc.PRESENTABLE_DATA = ANY_PRESENTABLE_DATA_SOURCE
vc.itemIndex = itemIndex
}
return vc
}
Ответ 3
Вот отличный репо для этого:
https://github.com/goktugyil/EZSwipeController
private func setupPageViewController() {
pageViewController = UIPageViewController(transitionStyle: UIPageViewControllerTransitionStyle.Scroll, navigationOrientation: UIPageViewControllerNavigationOrientation.Horizontal, options: nil)
pageViewController.dataSource = self
pageViewController.delegate = self
pageViewController.setViewControllers([stackPageVC[stackStartLocation]], direction: UIPageViewControllerNavigationDirection.Forward, animated: true, completion: nil)
pageViewController.view.frame = CGRect(x: 0, y: Constants.StatusBarHeight, width: Constants.ScreenWidth, height: Constants.ScreenHeightWithoutStatusBar)
pageViewController.view.backgroundColor = UIColor.clearColor()
addChildViewController(pageViewController)
view.addSubview(pageViewController.view)
pageViewController.didMoveToParentViewController(self)
}
Ответ 4
Я получил код Эрика Феррейры выше для работы (Xcode 6.4). Я хотел использовать контроллер просмотра страниц для отображения двух полностью уникальных контроллеров представлений с метками, в которых отображаются разные данные из базы данных Realm.
Я получил его для работы в тестовом проекте, в котором я использовал 2 раскадровки, каждая из которых содержала одну метку, установленную ее собственным классом, содержащим IBOutlet, на метку и код, устанавливающий текст ярлыка - это адекватно имитирует способ, которым я Я показываю данные своей базы данных Realm. Каждый класс раскадровки наследует параметр PageItemController, чтобы иметь доступную ему переменную itemIndex. PageItemController по очереди наследует UIViewController, завершающий цепочку наследования.
Я надеюсь, что это поможет кому-то, кто хочет использовать совершенно уникальные раскадровки.