how to pass data from UIPageViewController to chil

2019-03-06 23:26发布

问题:

I want to pass data from a UIPageViewController to one of its child ViewControllers. I have a protocol set like so:

protocol Delegate : class{
    func protocolMethod(count:Int)
}

And in UIPageViewController:

class PageVC : UIPageViewController{
    var delegate : Delegate?
    var count : Int = 1

    func classMethod(){
        self.displayPageForIndex(5) //this controlls the tranistion to the child ViewController 
        self.delegate?.protocolMethod(count : self.count) 
    }
}

In the conforming child ViewController:

class ChildVC : UIViewController , Delegate{

    func protocolMethod(count : Int){
        print(count)
    }

    override func viewDidLoad() { 
        super.viewDidLoad()
        let pvc = PageVC()
        pvc.delegate = self
    }
}

What I've done in viewDidLoad is the most simplistic solution I've tried, but still couldn't find the answer as to how to let the PageViewController know that the child ViewController is the receiver of the protocol method. If anyone could help me accomplish that without using prepareForSegue (as there are no segues) it would be very much appreciated.

回答1:

The problem is this line:

    let pvc = PageVC()

That makes a new, separate PageVC. That's not what you want. You want a reference to the existing, actual PageVC whose parent this is. That reference is self.parent (though not, perhaps, in viewDidLoad, which is rather early and might not guarantee that we are the child yet).



回答2:

If your child view controller knows that it's always going to be in the context of a UIPageViewController then you can use the parent/child links in the view controllers to allow those controllers to discover one another and exchange data. Particularly useful in those situations are the methods in the Responding to Containment Events section of the UIViewController class reference.

If you want to use a protocol then I would define the protocol on the page view controller and pass that protocol to the child view controller when I create it. So:

protocol MyDataSourceProtocol {
  func gimmeSomeData() -> Data
}

// The UIPageViewController implements MyDataSourceProtocol because
// he's going to provide information to his children.
class PageVC : UIPageViewController, MyDataSourceProtocol {
  func gimmeSomeData() -> Data {
      ...
  }

  func makeChildViewControllers() -> ChildViewControllers {
      return childControllerElements.map {
        element : ChildControllerElement in

        // pass self to let the child view controller know I'll be his
        // source
        return ChildViewController(self)
      }
  }
}

And then make sure your child view controller knows were to get stuff

class ChildViewController : UIViewController {
  let dataSource : MyDataSourceProtocol
  init(dataSource : MyDataSourceProtocol) {
    self.dataSource = dataSource
  }
}

Finally some comments on style:

You'll want to be careful with the term "delegate" as it has a very specific meaning in the context of Cocoa APIs and your use here does not match that meaning. Also naming a class with a lower case letter (childVC) is poor style.