У меня проблема с двумя моими дочерними контроллерами представления внутри родительского PageViewController, где делегат, вызываемый одним из дочерних элементов, не принимается другим дочерним элементом. Мой первый ребенок содержит ...

0
Anthony 14 Янв 2021 в 08:28

1 ответ

Лучший ответ

Я постараюсь быть ясным, надеюсь, так и будет, потому что английский не мой родной язык.

Мне кажется, что вы создаете экземпляры своих ViewControllers, которые будут представлены в методе getNewViewController(), и сохраняете их в массиве workoutViewControllers, но вы устанавливаете делегат как отдельный экземпляр, который вы никогда не устанавливали в своем PageVC . Вам нужно установить делегатов, используя одни и те же экземпляры.

Эти два являются двумя экземплярами двух классов VC (также не уверен, что идентификатор «DisplayViewController» правильный, я ожидал «DisplayMaplessViewController», жестко рассказать без раскадровки):

    let buttonsViewController = storyboard?.instantiateViewController(withIdentifier: "ButtonsViewController") as! ButtonsViewController
    let displayMaplessViewController = storyboard?.instantiateViewController(withIdentifier: "DisplayViewController") as! DisplayMaplessViewController
    
    buttonsViewController.buttonsDelegate = displayMaplessViewController

И это в массиве два других экземпляра , не связанные с приведенными выше, тех же двух классов :

    lazy var workoutViewControllers: [UIViewController] = {
    return [self.getNewViewController(viewController: "ButtonsViewController"), self.getNewViewController(viewController: "DisplayMaplessViewController")]
}()

Чтобы лучше понять, что я имею в виду, я реорганизовал с нуля и упростил ваш проект (пришлось делать это программно, так как я не привык к раскадровке). Теперь он состоит из PageController, который отображает buttonsVC с красной кнопкой и displayMaplessVC с синим фоном. Когда вы нажимаете красную кнопку, вызывается метод делегата, в результате чего синий фон становится зеленым.
Взгляните на то, что я делаю, поскольку я добавляю те же экземпляры, для которых я установил делегата:

  1. создать экземпляр объекта DisplayMaplessViewController и объекта ButtonsViewController;
  2. установить buttonsVC.buttonsDelegate = displayMaplessVC;
  3. добавьте оба ViewController в массив.

Это способ сделать это, но наверняка есть несколько других способов достичь того же результата. Как только вы поймете суть и поймете свою ошибку, вы сможете выбрать тот, который вам больше всего нравится.

Просто скопируйте и вставьте его в новый проект, соберите и запустите (вы должны установить класс начального ViewController в раскадровке как StartMaplessWorkoutPageViewController):

import UIKit

class StartMaplessWorkoutPageViewController: UIViewController, UIPageViewControllerDelegate, UIPageViewControllerDataSource {

private var workoutViewControllers = [UIViewController]()
private let pageController: UIPageViewController = {
    let pageController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
    return pageController
}()

override func viewDidLoad() {
    super.viewDidLoad()
    pageController.delegate = self
    pageController.dataSource = self
    let buttonsVC = ButtonsViewController()
    let displayMaplessVC = DisplayMaplessViewController()
    buttonsVC.buttonsDelegate = displayMaplessVC
    workoutViewControllers.append(buttonsVC)
    workoutViewControllers.append(displayMaplessVC)
    
    self.addChild(self.pageController)
    self.view.addSubview(self.pageController.view)

    self.pageController.setViewControllers([displayMaplessVC], direction: .forward, animated: true, completion: nil)

    self.pageController.didMove(toParent: self)
}

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    pageController.view.frame = view.bounds
}

func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
    
    guard let viewControllerIndex = workoutViewControllers.firstIndex(of: viewController) else {
         return nil
     }
     
     let previousIndex = viewControllerIndex - 1
     
     guard previousIndex >= 0 else {
         return workoutViewControllers.last
     }
     
     guard workoutViewControllers.count > previousIndex else {
         return nil
     }
     
     return workoutViewControllers[previousIndex]
}

func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
    
    guard let viewControllerIndex = workoutViewControllers.firstIndex(of: viewController) else {
        return nil
    }
    
    let nextIndex = viewControllerIndex + 1
    let workoutViewControllersCount = workoutViewControllers.count
    
    guard workoutViewControllersCount != nextIndex else {
        return workoutViewControllers.first
    }
    
    guard workoutViewControllersCount > nextIndex else {
        return nil
    }
    
    return workoutViewControllers[nextIndex]
}

func presentationCount(for pageViewController: UIPageViewController) -> Int {
    return workoutViewControllers.count
}

}

.

protocol ButtonsViewDelegate: class {
    func onButtonPressed()
}

import UIKit

class ButtonsViewController: UIViewController {

weak var buttonsDelegate: ButtonsViewDelegate?

let button: UIButton = {
    let button = UIButton()
    button.backgroundColor = .red
    button.addTarget(self, action: #selector(onButtonPressed), for: .touchUpInside)
    return button
}()

override func viewDidLoad() {
    super.viewDidLoad()
    view.addSubview(button)
}

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    button.frame = CGRect(x: 50,
                          y: 50,
                          width: 100,
                          height: 100)
}

@objc private func onButtonPressed() {
    buttonsDelegate?.onButtonPressed()
}

}

.

import UIKit

class DisplayMaplessViewController: UIViewController, ButtonsViewDelegate {

private let testView: UIView = {
    let view = UIView()
    view.backgroundColor = .blue
    return view
}()

override func viewDidLoad() {
    super.viewDidLoad()
    view.addSubview(testView)
}

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    testView.frame = view.bounds
}

internal func onButtonPressed() {
    testView.backgroundColor = .green
}

}
1
oneshot 14 Янв 2021 в 10:48