I need a UIPageViewController to display as many UIViewControllers as the data available in an array. Let's say I have an array of Int and for each of this Int I want a UIViewController to display one of them in a UILabel. To accomplish this I've created in my Main storyboard both the UIPageViewController and UIViewController with its UILabel.
This is the code I've written for the UIPageViewController:
import UIKit
import RealmSwift
class PageViewController: UIPageViewController, UIPageViewControllerDataSource {
lazy var subViewControllers: [UIViewController] = {
return [
self.createNewVC(withName: "CounterViewController"),
self.createNewVC(withName: "CounterViewController"),
self.createNewVC(withName: "CounterViewController")
]
}()
var dataArray: [Int] = [30, 134, 345]
override func viewDidLoad() {
super.viewDidLoad()
self.dataSource = self
setViewControllers([subViewControllers[0]], direction: .forward, animated: true, completion: nil)
}
// Creates a new ViewController
func createNewVC(withName name: String) -> UIViewController {
return UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: name)
}
// Returns the previous ViewController
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
let currentIndex: Int = subViewControllers.index(of: viewController) ?? 0
if (currentIndex <= 0) {
return nil
}
if let previous = subViewControllers[currentIndex - 1] as? CounterViewController {
previous.daysLeftLabel.text = String(dataArray[currentIndex])
return previous
} else {
return nil
}
}
// Returns the next ViewController
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
let currentIndex: Int = subViewControllers.index(of: viewController) ?? 0
if (currentIndex >= subViewControllers.count - 1) {
return nil
}
if let next = subViewControllers[currentIndex + 1] as? CounterViewController {
next.daysLeftLabel.text = "0"
return next
} else {
return nil
}
}
}
and this is the code for the UIViewController
import UIKit
class CounterViewController: UIViewController {
@IBOutlet weak var daysLeftLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
NB: "CounterViewController" is also the UIViewController StoryBoardID
The problem is that when I scroll for the first time to the right the app crashes at this line next.daysLeftLabel.text = "0"
saying that it found a nil value while unwrapping Optional.
What am I doing wrong here?
Also I want to take the opportunity to ask something. In this case, as you may have guessed, I am using a UIPageViewController which holds the same UIViewControllers but with different data displayed, which is the best way to accomplish this? Am I doing it correctly or there is an easier and cleaner way?
This line crashes
next.daysLeftLabel.text = "0"
because daysLeftLabel
is nil until the VC loads , you need
class CounterViewController: UIViewController {
@IBOutlet weak var daysLeftLabel: UILabel!
var sendedText = ""
override func viewDidLoad() {
super.viewDidLoad()
daysLeftLabel.text = sendedText
// Do any additional setup after loading the view.
}
}
Then use
next.sendedText = "0"