When I set transitionStyle: .scroll for UIPageViewController, I get a bug in the following steps:
- Run the application, click on the button, set the number 10, click "OK"
- Swipe forward Swipe back
The button displays the number 0 (instead of the number 10)
With transitionStyle: .pageCurl, this bug is gone. What's wrong with my code?
My project: https://yadi.sk/d/A2MJf8c972Bcdw
Here is my code:
File SceneDelegate:
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(frame: windowScene.coordinateSpace.bounds)
window?.windowScene = windowScene
window?.rootViewController = MainTabBarController()
window?.makeKeyAndVisible()
}
func sceneDidDisconnect(_ scene: UIScene) {
}
func sceneDidBecomeActive(_ scene: UIScene) {
}
func sceneWillResignActive(_ scene: UIScene) {
}
func sceneWillEnterForeground(_ scene: UIScene) {
}
func sceneDidEnterBackground(_ scene: UIScene) {
}
}
File MainTabBarController:
import UIKit
class MainTabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
let firstVC = PageViewController()
let secondVC = SecondViewController()
let firstImage = UIImage(systemName: "heart")!
let secondImage = UIImage(systemName: "circle")!
viewControllers = [
generateNavigationController(rootViewController: firstVC, title: "First", image: firstImage),
generateNavigationController(rootViewController: secondVC, title: "Second", image: secondImage)
]
}
private func generateNavigationController(rootViewController: UIViewController, title: String, image: UIImage) -> UIViewController {
let navigationVC = UINavigationController(rootViewController: rootViewController)
navigationVC.tabBarItem.title = title
navigationVC.tabBarItem.image = image
return navigationVC
}
}
File ModelOne:
import RealmSwift
class ModelOne: Object {
@objc dynamic var property = "0"
@objc dynamic var color = "green"
func createModelOne() {
if realmOne.objects(ModelOne.self).filter("color = 'green'").count == 0 {
let newModel = ModelOne()
newModel.color = "green"
StorageManagerOne.saveObject(newModel)
}
}
}
File ModelTwo:
import RealmSwift
class ModelTwo: Object {
@objc dynamic var property = "0"
@objc dynamic var speed = "200"
func createModelTwo() {
if realmTwo.objects(ModelTwo.self).filter("speed = '200'").count == 0 {
let newModel = ModelTwo()
newModel.speed = "200"
StorageManagerTwo.saveObject(newModel)
}
}
}
File StorageManagerOne:
import RealmSwift
let realmOne = try! Realm()
class StorageManagerOne {
static func saveObject(_ object: ModelOne) {
try! realmOne.write {
realmOne.add(object)
}
}
static func deleteObject(_ object: ModelOne) {
try! realmOne.write {
realmOne.delete(object)
}
}
}
File StorageManagerTwo:
import RealmSwift
let realmTwo = try! Realm()
class StorageManagerTwo {
static func saveObject(_ object: ModelTwo) {
try! realmTwo.write {
realmTwo.add(object)
}
}
static func deleteObject(_ object: ModelTwo) {
try! realmTwo.write {
realmTwo.delete(object)
}
}
}
File ViewController:
import UIKit
class ViewController: UIViewController {
let pageControl = UIPageControl()
var currentPage = 0
var numberOfPage = 0
var valueText = ""
let valueButton = UIButton()
let mainView = UIView()
var modelOne: ModelOne?
var modelTwo: ModelTwo?
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
view.backgroundColor = .systemBackground
modelOne = realmOne.objects(ModelOne.self).filter("color = 'green'")[0]
modelTwo = realmTwo.objects(ModelTwo.self).filter("speed = '200'")[0]
configuration()
}
func configuration() {
pageControl.numberOfPages = numberOfPage
pageControl.currentPage = currentPage
pageControl.pageIndicatorTintColor = .gray
pageControl.currentPageIndicatorTintColor = .blue
valueButton.backgroundColor = .systemBlue
valueButton.layer.cornerRadius = 20.0
valueButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 20.0)
valueButton.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
valueButton.setTitle(valueText, for: .normal)
mainView.backgroundColor = .yellow
mainView.layer.cornerRadius = 15.0
mainView.addSubview(valueButton)
self.view.addSubview(mainView)
self.view.addSubview(pageControl)
pageControl.translatesAutoresizingMaskIntoConstraints = false
mainView.translatesAutoresizingMaskIntoConstraints = false
valueButton.translatesAutoresizingMaskIntoConstraints = false
let guide = self.view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
valueButton.centerXAnchor.constraint(equalTo: mainView.centerXAnchor),
valueButton.topAnchor.constraint(equalTo: mainView.topAnchor, constant: 10),
valueButton.heightAnchor.constraint(equalToConstant: 40),
valueButton.widthAnchor.constraint(equalToConstant: 115),
mainView.leadingAnchor.constraint(equalTo: guide.leadingAnchor, constant: 10),
mainView.trailingAnchor.constraint(equalTo: guide.trailingAnchor, constant: -10),
mainView.topAnchor.constraint(equalTo: guide.topAnchor, constant: 20),
mainView.bottomAnchor.constraint(equalTo: valueButton.bottomAnchor, constant: 20),
pageControl.leadingAnchor.constraint(equalTo: guide.leadingAnchor, constant: 10),
pageControl.trailingAnchor.constraint(equalTo: guide.trailingAnchor, constant: -10),
pageControl.topAnchor.constraint(equalTo: mainView.bottomAnchor, constant: 20),
pageControl.heightAnchor.constraint(equalToConstant: 30),
])
}
@objc func buttonTapped(sender: UIButton!) {
var value: String?
let alertEdit = UIAlertController(title: currentPage == 0 ?
"Please, add modelOne" : "Please, add modelTwo",
message: "",
preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK", style: .default) { action in
let textField = alertEdit.textFields! [0]
if (textField.text?.isEmpty == true) {
value = "0"
}
else {
value = textField.text!
}
if self.currentPage == 0 {
try! realmOne.write {
self.modelOne!.property = value!
self.valueButton.setTitle(self.modelOne!.property, for: .normal)
}
}
else {
try! realmTwo.write {
self.modelTwo!.property = value!
self.valueButton.setTitle(self.modelTwo!.property, for: .normal)
}
}
}
let cancelAction = UIAlertAction(title: "Cancel", style: .default) { _ in }
alertEdit.addAction(okAction)
alertEdit.addAction(cancelAction)
alertEdit.addTextField {(targetTF) in
if self.currentPage == 0 {
targetTF.text = self.modelOne!.property == "0" ? "" : self.modelOne!.property
}
else {
targetTF.text = self.modelTwo!.property == "0" ? "" : self.modelTwo!.property
}
targetTF.keyboardType = .asciiCapableNumberPad
targetTF.placeholder = "0"
}
self.present(alertEdit, animated: true, completion: nil)
}
}
File PageViewController:
import UIKit
class PageViewController: UIPageViewController {
var listValue: [String]?
override init(transitionStyle style: UIPageViewController.TransitionStyle, navigationOrientation: UIPageViewController.NavigationOrientation, options: [UIPageViewController.OptionsKey : Any]? = nil) {
super.init(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
dataSource = self
if let viewController = showViewControllerAtIndex(0) {
setViewControllers([viewController],
direction: .forward,
animated: false,
completion: nil)
}
}
func showViewControllerAtIndex(_ index: Int) -> ViewController? {
ModelOne().createModelOne()
let modelOne = realmOne.objects(ModelOne.self).filter("color = 'green'")[0]
ModelTwo().createModelTwo()
let modelTwo = realmTwo.objects(ModelTwo.self).filter("speed = '200'")[0]
listValue = [modelOne.property, modelTwo.property]
guard index >= 0 && index < listValue!.count else { return nil }
let viewController = ViewController()
viewController.valueText = listValue![index]
viewController.currentPage = index
viewController.numberOfPage = listValue!.count
return viewController
}
}
extension PageViewController: UIPageViewControllerDataSource {
func pageViewController(_ pageViewController: UIPageViewController,
viewControllerBefore viewController: UIViewController) -> UIViewController? {
var pageNumber = (viewController as! ViewController).currentPage
pageNumber -= 1
// var pageNumber = (viewController as! ViewController).currentPage
// if (viewController as! ViewController).currentPage > 0 {
// print("before \(pageNumber)")
// pageNumber -= 1
// }
return showViewControllerAtIndex(pageNumber)
}
func pageViewController(_ pageViewController: UIPageViewController,
viewControllerAfter viewController: UIViewController) -> UIViewController? {
var pageNumber = (viewController as! ViewController).currentPage
pageNumber += 1
// var pageNumber = (viewController as! ViewController).currentPage
// if (viewController as! ViewController).currentPage == 0 {
// print("after \(pageNumber)")
// pageNumber += 1
// }
return showViewControllerAtIndex(pageNumber)
}
}
File SecondViewController:
import UIKit
class SecondViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .green
}
}