ios Swift:UIPageViewController - 加载单独的视图
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28402041/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Swift: UIPageViewController - Load separate views
提问by DannieCoderBoi
I'm following this tutorial: http://swiftiostutorials.com/ios-tutorial-using-uipageviewcontroller-create-content-slider-objective-cswift/to create an app that shows multiple sliders.
我正在关注本教程:http: //swiftiostutorials.com/ios-tutorial-using-uipageviewcontroller-create-content-slider-objective-cswift/以创建一个显示多个滑块的应用程序。
Even though i've got this tutorial to work, This example only changes an image based on those that are stored in an array.
即使我已经开始使用本教程,此示例也仅根据存储在数组中的图像更改图像。
How can I get it to load ViewControllers instead of images
我怎样才能让它加载 ViewControllers 而不是图像
I have 4 ViewControllers:
我有 4 个视图控制器:
- ViewController1
- ViewController2
- ViewController3
- ViewController4
- 视图控制器1
- 视图控制器2
- 视图控制器3
- 视图控制器4
I would like slide one to show ViewController1 and slide2 to load ViewController2 etc....
我想要一张幻灯片来显示 ViewController1 和幻灯片 2 来加载 ViewController2 等......
Here is my main ViewController:
这是我的主要 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
}
and here is my PageItemController:
这是我的 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)
}
}
I'm new to Swift/iOS Development and really trying to get into it by developing. Thank you in advance for your answers :)
我是 Swift/iOS 开发的新手,并且真的试图通过开发来进入它。预先感谢您的回答:)
EDIT: To Make Question Clear
编辑:使问题清楚
How do I make it so that there is an array of view controllers that correspond to the slide left/right of the UIPageViewController?
我如何制作它以便有一组视图控制器对应于 UIPageViewController 的左侧/右侧幻灯片?
So when I swipe left on ViewController1 - the UIViewController2 is loaded and reverse for swipe right.
因此,当我在 ViewController1 上向左滑动时 - UIViewController2 已加载并反转以向右滑动。
回答by Eric F.
Assuming you have view controllers 1-4 defined in the same storyboard as your UIPageViewController, and you have their Storyboard IDs set as ViewController0, ViewController1, and et cetera, then create a method to populate your view controller array and call it in your viewDidLoad()
before calling createPageViewController()
假设您在与 UIPageViewController 相同的故事板中定义了视图控制器 1-4,并且将它们的故事板 ID 设置为 ViewController0、ViewController1 等,然后创建一个方法来填充您的视图控制器数组并viewDidLoad()
在调用之前调用它createPageViewController()
override func viewDidLoad() {
super.viewDidLoad()
populateControllersArray()
createPageViewController()
setupPageControl()
}
Implement the method like so:
像这样实现方法:
var controllers = [PageItemController]()
func populateControllersArray() {
for i in 0...3 {
let controller = storyboard!.instantiateViewControllerWithIdentifier("ViewController\(i)") as PageItemController
controller.itemIndex = i
controllers.append(controller)
}
}
And define your createPageViewController()
as the following
并将您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)
}
then in your two delegate before and after methods:
然后在你的两个委托之前和之后的方法中:
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
}
And in the count method
并在计数方法中
func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int {
return controllers.count
}
In fact, you can populate controllers
with any view controllers you want to display, just set their class as PageItemController in storyboard (in order to have index property).
事实上,你可以填充controllers
任何你想显示的视图控制器,只需在故事板中将它们的类设置为 PageItemController (为了有 index 属性)。
Or you can set each view controller as it's own class, and use runtime property getting and setting.
或者您可以将每个视图控制器设置为它自己的类,并使用运行时属性获取和设置。
Use controller.valueForKey("itemIndex") as Int
in the before and after method instead of controller.itemIndex
使用controller.valueForKey("itemIndex") as Int
前和方法,而不是后的controller.itemIndex
Use controller.setValue(i, forKey: "itemIndex")
instead of controller.itemIndex = i
in populateControllersArray()
.
使用controller.setValue(i, forKey: "itemIndex")
而不是controller.itemIndex = i
in populateControllersArray()
。
Just ensure that each controller class has the Int
property itemIndex
, or your application will crash.
只需确保每个控制器类都具有该Int
属性itemIndex
,否则您的应用程序将崩溃。
To bring it all together in your code, do the following:
要将所有内容整合到您的代码中,请执行以下操作:
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
}
回答by ergoon
You do load ViewControllers for every page. every image that you show is inside it's own ViewController. That is done through:
您确实为每个页面加载了 ViewControllers。您显示的每个图像都在它自己的 ViewController 中。这是通过以下方式完成的:
private func getItemController(itemIndex: Int) -> PageItemController?
if every page of yours uses the same layout, there is nothing left to do here, except designing this ViewController in the Interface Builder. If, however, every page uses a different layout and shows different data, you would first prototype/design those ViewControllers in Interface Builder.
如果您的每个页面都使用相同的布局,那么除了在 Interface Builder 中设计这个 ViewController 之外,这里没有什么可做的。但是,如果每个页面使用不同的布局并显示不同的数据,您将首先在 Interface Builder 中原型/设计这些 ViewController。
then you would create classes for every ViewController and extend them from PageItemController. You only keep the index variable in PageItemController and move the rest of your logic to the subclasses.
然后您将为每个 ViewController 创建类并从 PageItemController 扩展它们。您只需将 index 变量保留在 PageItemController 中,并将其余逻辑移动到子类中。
import UIKit
class PageItemController: UIViewController {
// MARK: - Variables
var itemIndex: Int = 0
}
for example a viewController that holds an image
例如一个包含图像的 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)
}
}
finally you just change your getItemController
function to return the correct ViewController for the specified index. here you either pass data to the ViewController or you just return it.
最后,您只需更改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
}
回答by Esqarrouth
Here is a great repo for this:
这是一个很好的回购:
https://github.com/goktugyil/EZSwipeController
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)
}
回答by Delete My Account
I got Eric Ferreira's code above to work (Xcode 6.4). I wanted to use a Page View Controller to display two completely unique view controllers with labels that displays different data from a Realm database.
我让上面的 Eric Ferreira 的代码可以工作(Xcode 6.4)。我想使用页面视图控制器来显示两个完全独特的带有标签的视图控制器,这些标签显示来自 Realm 数据库的不同数据。
I got it to work in a test project where I used 2 storyboards, each containing a single label that is set by its own class containing the IBOutlet to the label and code setting the label text -- this adequately simulates the way I am displaying my Realm database data. Each storyboard class inherits the PageItemController so as to have the "itemIndex" variable available to it. The PageItemController in turns inherits UIViewController completing the inheritance chain.
我让它在一个测试项目中工作,我使用了 2 个故事板,每个故事板都包含一个标签,该标签由它自己的类设置,其中包含 IBOutlet 到标签和设置标签文本的代码——这充分模拟了我显示我的方式领域数据库数据。每个故事板类都继承了 PageItemController 以便“itemIndex”变量可用。PageItemController 依次继承 UIViewController 完成继承链。
I hope this helps someone that is seeking to use completely unique storyboards.
我希望这可以帮助那些正在寻求使用完全独特的故事板的人。