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.
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).
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.