Question
In the process of building an application, we will inevitably encounter UI / UX like this
To solve this problem, most people will choose to include a CollectionView in a CollectionView. This approach is very good, solving many cases. However, if you do not handle the Layout as well as the Reuse management of CollectionView, it will cause many annoying Bugs about the UI. In today’s article, I will introduce another approach to solve the above problem, which is to use UIPageViewController.
Introducing the UIPageViewController
UIPageViewController is a Component of UIKit. UIPageViewController can be understood as an array of ViewController and at a time will display only 1 Controller (exactly the view of that ViewController, but in this article I would like to call Controlller for short. and these Controllers can switch back and forth (left, right) according to different transition effects during initialization.
UIPageViewController can be used in many cases. However, as I see, when searching for how to use UIPageViewController does not produce much documentation. Swift also doesn’t have much support for this component. If you implement the default Apple UIPageViewController will clearly see that. UIPageViewControllerDelegate also only has two functions called when a controller’s view is about to transition to the next controller’s view in Pages.
To make it easier to use and extend the UIPageViewController, we will have to add some Custom functions. The next part of the article I will go into each specific step.
Custom UIPageViewController
First, I want to receive events when the Controller displays on the Page changes with the corresponding Index. Above I mentioned 2 functions in default Delegate, but these 2 functions are not always called. Therefore, I will create a Delegate to capture this event.
1 2 3 4 | <span class="token keyword">protocol</span> <span class="token builtin">CustomPageViewControllerDelegate</span> <span class="token punctuation">:</span> <span class="token builtin">AnyObject</span> <span class="token punctuation">{</span> <span class="token keyword">func</span> <span class="token function">pageViewController</span> <span class="token punctuation">(</span> pageViewController <span class="token punctuation">:</span> <span class="token builtin">CustomPageViewController</span> <span class="token punctuation">,</span> didUpdatePageIndex index <span class="token punctuation">:</span> <span class="token builtin">Int</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> |
Create a CustomPageViewController class that inherits the UIPageViewController
1 2 3 4 5 6 | <span class="token keyword">class</span> <span class="token class-name">CustomPageViewController</span> <span class="token punctuation">:</span> <span class="token builtin">UIPageViewController</span> <span class="token punctuation">{</span> <span class="token keyword">override</span> <span class="token keyword">func</span> <span class="token function">viewDidLoad</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">super</span> <span class="token punctuation">.</span> <span class="token function">viewDidLoad</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
I will declare the controller property to contain a Controller array which is the Controllers displayed on UIPageViewController and a delegate of type CustomPageViewControllerDelegate I defined above. Remember to weak to avoid the Retain Cycle.
1 2 3 4 5 6 7 8 9 | <span class="token keyword">class</span> <span class="token class-name">CustomPageViewController</span> <span class="token punctuation">:</span> <span class="token builtin">UIPageViewController</span> <span class="token punctuation">{</span> <span class="token keyword">weak</span> <span class="token keyword">var</span> customDelegate <span class="token punctuation">:</span> <span class="token builtin">CustomPageViewControllerDelegate</span> <span class="token operator">?</span> <span class="token keyword">var</span> controllers <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token builtin">UIViewController</span> <span class="token punctuation">]</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">override</span> <span class="token keyword">func</span> <span class="token function">viewDidLoad</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">super</span> <span class="token punctuation">.</span> <span class="token function">viewDidLoad</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
The mechanism of UIPageViewController at a time sets a Controller, and pre-creates Controller (Will display when swiping left) and Controller after (Will show when swiping right) of that Controller. Therefore, when for CustomPageViewController conform UIPageViewControllerDataSource, we will have to declare two functions.
1 2 3 4 5 6 7 8 | <span class="token keyword">extension</span> <span class="token builtin">CustomPageViewController</span> <span class="token punctuation">:</span> <span class="token builtin">UIPageViewControllerDataSource</span> <span class="token punctuation">{</span> <span class="token keyword">func</span> <span class="token function">pageViewController</span> <span class="token punctuation">(</span> <span class="token number">_</span> <span class="token punctuation">:</span> <span class="token builtin">UIPageViewController</span> <span class="token punctuation">,</span> viewControllerBefore viewController <span class="token punctuation">:</span> <span class="token builtin">UIViewController</span> <span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token builtin">UIViewController</span> <span class="token operator">?</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> <span class="token keyword">func</span> <span class="token function">pageViewController</span> <span class="token punctuation">(</span> <span class="token number">_</span> <span class="token punctuation">:</span> <span class="token builtin">UIPageViewController</span> <span class="token punctuation">,</span> viewControllerAfter viewController <span class="token punctuation">:</span> <span class="token builtin">UIViewController</span> <span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token builtin">UIViewController</span> <span class="token operator">?</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Add the following code to those two functions. The logic of this code is relatively simple, we will check how much index controller is displayed. Subtract 1 from the indext to get the previous Controller index in the array controlles, if the index is valid then the corresponding element is returned, otherwise nil is returned. Similar to the afterController finder logic.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <span class="token keyword">extension</span> <span class="token builtin">CustomPageViewController</span> <span class="token punctuation">:</span> <span class="token builtin">UIPageViewControllerDataSource</span> <span class="token punctuation">{</span> <span class="token keyword">func</span> <span class="token function">pageViewController</span> <span class="token punctuation">(</span> <span class="token number">_</span> <span class="token punctuation">:</span> <span class="token builtin">UIPageViewController</span> <span class="token punctuation">,</span> viewControllerBefore viewController <span class="token punctuation">:</span> <span class="token builtin">UIViewController</span> <span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token builtin">UIViewController</span> <span class="token operator">?</span> <span class="token punctuation">{</span> <span class="token keyword">guard</span> <span class="token keyword">let</span> controllerIndex <span class="token operator">=</span> controllers <span class="token punctuation">.</span> <span class="token function">firstIndex</span> <span class="token punctuation">(</span> of <span class="token punctuation">:</span> viewController <span class="token punctuation">)</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token constant">nil</span> <span class="token punctuation">}</span> <span class="token keyword">let</span> previousIndex <span class="token operator">=</span> controllerIndex <span class="token operator">-</span> <span class="token number">1</span> <span class="token keyword">if</span> previousIndex <span class="token operator">>=</span> <span class="token number">0</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> controllers <span class="token punctuation">[</span> previousIndex <span class="token punctuation">]</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token constant">nil</span> <span class="token punctuation">}</span> <span class="token keyword">func</span> <span class="token function">pageViewController</span> <span class="token punctuation">(</span> <span class="token number">_</span> <span class="token punctuation">:</span> <span class="token builtin">UIPageViewController</span> <span class="token punctuation">,</span> viewControllerAfter viewController <span class="token punctuation">:</span> <span class="token builtin">UIViewController</span> <span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token builtin">UIViewController</span> <span class="token operator">?</span> <span class="token punctuation">{</span> <span class="token keyword">guard</span> <span class="token keyword">let</span> controllerIndex <span class="token operator">=</span> controllers <span class="token punctuation">.</span> <span class="token function">firstIndex</span> <span class="token punctuation">(</span> of <span class="token punctuation">:</span> viewController <span class="token punctuation">)</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token constant">nil</span> <span class="token punctuation">}</span> <span class="token keyword">let</span> nextIndex <span class="token operator">=</span> controllerIndex <span class="token operator">+</span> <span class="token number">1</span> <span class="token keyword">if</span> nextIndex <span class="token operator"><</span> controllers <span class="token punctuation">.</span> <span class="token builtin">count</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> controllers <span class="token punctuation">[</span> nextIndex <span class="token punctuation">]</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token constant">nil</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Declare the notifyfNewIndex () function to trigger the delegate when new controller is displayed, index changes.
1 2 3 4 5 6 7 | <span class="token keyword">private</span> <span class="token keyword">func</span> <span class="token function">notifyfNewIndex</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token keyword">let</span> firstViewController <span class="token operator">=</span> viewControllers <span class="token operator">?</span> <span class="token punctuation">.</span> <span class="token builtin">first</span> <span class="token punctuation">,</span> <span class="token keyword">let</span> index <span class="token operator">=</span> controllers <span class="token punctuation">.</span> <span class="token function">firstIndex</span> <span class="token punctuation">(</span> of <span class="token punctuation">:</span> firstViewController <span class="token punctuation">)</span> <span class="token punctuation">{</span> customDelegate <span class="token operator">?</span> <span class="token punctuation">.</span> <span class="token function">pageViewController</span> <span class="token punctuation">(</span> pageViewController <span class="token punctuation">:</span> <span class="token keyword">self</span> <span class="token punctuation">,</span> didUpdatePageIndex <span class="token punctuation">:</span> index <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Declare the scrollToViewController function. The purpose of this function is called in case we want to specify a ViewController to display. Then we have to call the UIPageViewController’s setViewControlles function. This function we will not use directly, so we will declare Private.
1 2 3 4 5 6 7 8 9 10 | <span class="token keyword">private</span> <span class="token keyword">func</span> <span class="token function">scrollToViewController</span> <span class="token punctuation">(</span> viewController <span class="token punctuation">:</span> <span class="token builtin">UIViewController</span> <span class="token punctuation">,</span> direction <span class="token punctuation">:</span> <span class="token builtin">UIPageViewController</span> <span class="token punctuation">.</span> <span class="token builtin">NavigationDirection</span> <span class="token operator">=</span> <span class="token punctuation">.</span> forward <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">setViewControllers</span> <span class="token punctuation">(</span> <span class="token punctuation">[</span> viewController <span class="token punctuation">]</span> <span class="token punctuation">,</span> direction <span class="token punctuation">:</span> direction <span class="token punctuation">,</span> animated <span class="token punctuation">:</span> <span class="token boolean">true</span> <span class="token punctuation">,</span> completion <span class="token punctuation">:</span> <span class="token punctuation">{</span> <span class="token number">_</span> <span class="token keyword">in</span> <span class="token keyword">self</span> <span class="token punctuation">.</span> <span class="token function">notifyfNewIndex</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> |
Our Controllers are in an array with corresponding indexes, during use we want to access the specific viewController via index. Therefore, we will declare function func scrollToViewController (index newIndex: Int) viewControllers? .First returns the currently displayed Controller. Find the corresponding index of that firstViewController in the array controllers. Compare the newIndex with the index just found to decide whether the scroll direction is forward or reverse. Then call the scrollToViewController function declared in the above paragraph to reset the displayed controller
1 2 3 4 5 6 7 8 9 | <span class="token keyword">func</span> <span class="token function">scrollToViewController</span> <span class="token punctuation">(</span> index newIndex <span class="token punctuation">:</span> <span class="token builtin">Int</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token keyword">let</span> firstViewController <span class="token operator">=</span> viewControllers <span class="token operator">?</span> <span class="token punctuation">.</span> <span class="token builtin">first</span> <span class="token punctuation">,</span> <span class="token keyword">let</span> currentIndex <span class="token operator">=</span> controllers <span class="token punctuation">.</span> <span class="token function">firstIndex</span> <span class="token punctuation">(</span> of <span class="token punctuation">:</span> firstViewController <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">let</span> direction <span class="token punctuation">:</span> <span class="token builtin">UIPageViewController</span> <span class="token punctuation">.</span> <span class="token builtin">NavigationDirection</span> <span class="token operator">=</span> newIndex <span class="token operator">>=</span> currentIndex <span class="token operator">?</span> <span class="token punctuation">.</span> forward <span class="token punctuation">:</span> <span class="token punctuation">.</span> <span class="token builtin">reverse</span> <span class="token keyword">let</span> nextViewController <span class="token operator">=</span> controllers <span class="token punctuation">[</span> newIndex <span class="token punctuation">]</span> <span class="token function">scrollToViewController</span> <span class="token punctuation">(</span> viewController <span class="token punctuation">:</span> nextViewController <span class="token punctuation">,</span> direction <span class="token punctuation">:</span> direction <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Conform UIPageViewControllerDelegate. And declare the following code. This function will be called when viewController is called when we swipe between Controllers sequentially. But will not go in when we call the setViewController function of UIPageViewController. Therefore, we need to handle both cases, calling notifyfNewIndex () function to delegate to capture the event.
1 2 3 4 5 6 7 8 9 10 | <span class="token keyword">extension</span> <span class="token builtin">CustomPageViewController</span> <span class="token punctuation">:</span> <span class="token builtin">UIPageViewControllerDelegate</span> <span class="token punctuation">{</span> <span class="token keyword">func</span> <span class="token function">pageViewController</span> <span class="token punctuation">(</span> <span class="token number">_</span> <span class="token punctuation">:</span> <span class="token builtin">UIPageViewController</span> <span class="token punctuation">,</span> didFinishAnimating <span class="token number">_</span> <span class="token punctuation">:</span> <span class="token builtin">Bool</span> <span class="token punctuation">,</span> previousViewControllers <span class="token number">_</span> <span class="token punctuation">:</span> <span class="token punctuation">[</span> <span class="token builtin">UIViewController</span> <span class="token punctuation">]</span> <span class="token punctuation">,</span> transitionCompleted <span class="token number">_</span> <span class="token punctuation">:</span> <span class="token builtin">Bool</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">notifyfNewIndex</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Add some functions in viewDidLoad. We need to set the default controller to show up for the PageViewController, I will choose to be the first controller in the array.
1 2 3 4 5 6 7 8 9 | <span class="token keyword">override</span> <span class="token keyword">func</span> <span class="token function">viewDidLoad</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">super</span> <span class="token punctuation">.</span> <span class="token function">viewDidLoad</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> dataSource <span class="token operator">=</span> <span class="token keyword">self</span> delegate <span class="token operator">=</span> <span class="token keyword">self</span> <span class="token keyword">if</span> <span class="token keyword">let</span> initialViewController <span class="token operator">=</span> controllers <span class="token punctuation">.</span> <span class="token builtin">first</span> <span class="token punctuation">{</span> <span class="token function">scrollToViewController</span> <span class="token punctuation">(</span> viewController <span class="token punctuation">:</span> initialViewController <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Use CustomPageViewController
The script here will look like the example at the beginning of the post. So I will create a simple Controller including 1 CollectionView and random Color displayed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | <span class="token keyword">class</span> <span class="token class-name">ColorViewController</span> <span class="token punctuation">:</span> <span class="token builtin">UIViewController</span> <span class="token punctuation">{</span> <span class="token keyword">private</span> <span class="token keyword">var</span> collectionView <span class="token punctuation">:</span> <span class="token builtin">UICollectionView</span> <span class="token operator">!</span> <span class="token keyword">private</span> <span class="token keyword">let</span> randomColors <span class="token punctuation">:</span> <span class="token punctuation">[</span> <span class="token builtin">UIColor</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token punctuation">.</span> red <span class="token punctuation">,</span> <span class="token punctuation">.</span> yellow <span class="token punctuation">,</span> <span class="token punctuation">.</span> blue <span class="token punctuation">,</span> <span class="token punctuation">.</span> orange <span class="token punctuation">,</span> <span class="token punctuation">.</span> purple <span class="token punctuation">,</span> <span class="token punctuation">.</span> systemPink <span class="token punctuation">,</span> <span class="token punctuation">.</span> brown <span class="token punctuation">]</span> <span class="token keyword">override</span> <span class="token keyword">func</span> <span class="token function">viewDidLoad</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">configView</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">private</span> <span class="token keyword">func</span> <span class="token function">configView</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">let</span> layout <span class="token operator">=</span> <span class="token function">UICollectionViewFlowLayout</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> layout <span class="token punctuation">.</span> itemSize <span class="token operator">=</span> <span class="token function">CGSize</span> <span class="token punctuation">(</span> width <span class="token punctuation">:</span> <span class="token number">70</span> <span class="token punctuation">,</span> height <span class="token punctuation">:</span> <span class="token number">70</span> <span class="token punctuation">)</span> layout <span class="token punctuation">.</span> minimumLineSpacing <span class="token operator">=</span> <span class="token number">15</span> layout <span class="token punctuation">.</span> minimumInteritemSpacing <span class="token operator">=</span> <span class="token number">15</span> layout <span class="token punctuation">.</span> sectionInset <span class="token operator">=</span> <span class="token function">UIEdgeInsets</span> <span class="token punctuation">(</span> top <span class="token punctuation">:</span> <span class="token number">0</span> <span class="token punctuation">,</span> <span class="token keyword">left</span> <span class="token punctuation">:</span> <span class="token number">15</span> <span class="token punctuation">,</span> bottom <span class="token punctuation">:</span> <span class="token number">0</span> <span class="token punctuation">,</span> <span class="token keyword">right</span> <span class="token punctuation">:</span> <span class="token number">15</span> <span class="token punctuation">)</span> collectionView <span class="token operator">=</span> <span class="token function">UICollectionView</span> <span class="token punctuation">(</span> frame <span class="token punctuation">:</span> <span class="token punctuation">.</span> zero <span class="token punctuation">,</span> collectionViewLayout <span class="token punctuation">:</span> layout <span class="token punctuation">)</span> view <span class="token punctuation">.</span> <span class="token function">addSubview</span> <span class="token punctuation">(</span> collectionView <span class="token punctuation">)</span> collectionView <span class="token punctuation">.</span> snp <span class="token punctuation">.</span> makeConstraints <span class="token punctuation">{</span> $ <span class="token number">0</span> <span class="token punctuation">.</span> edges <span class="token punctuation">.</span> <span class="token function">equalToSuperview</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> collectionView <span class="token punctuation">.</span> backgroundColor <span class="token operator">=</span> <span class="token punctuation">.</span> clear collectionView <span class="token punctuation">.</span> dataSource <span class="token operator">=</span> <span class="token keyword">self</span> collectionView <span class="token punctuation">.</span> <span class="token function">register</span> <span class="token punctuation">(</span> <span class="token builtin">UICollectionViewCell</span> <span class="token punctuation">.</span> <span class="token keyword">self</span> <span class="token punctuation">,</span> forCellWithReuseIdentifier <span class="token punctuation">:</span> <span class="token string">"Cell"</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">extension</span> <span class="token builtin">ColorViewController</span> <span class="token punctuation">:</span> <span class="token builtin">UICollectionViewDataSource</span> <span class="token punctuation">{</span> <span class="token keyword">func</span> <span class="token function">collectionView</span> <span class="token punctuation">(</span> <span class="token number">_</span> collectionView <span class="token punctuation">:</span> <span class="token builtin">UICollectionView</span> <span class="token punctuation">,</span> numberOfItemsInSection section <span class="token punctuation">:</span> <span class="token builtin">Int</span> <span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token builtin">Int</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token number">20</span> <span class="token punctuation">}</span> <span class="token keyword">func</span> <span class="token function">collectionView</span> <span class="token punctuation">(</span> <span class="token number">_</span> collectionView <span class="token punctuation">:</span> <span class="token builtin">UICollectionView</span> <span class="token punctuation">,</span> cellForItemAt indexPath <span class="token punctuation">:</span> <span class="token builtin">IndexPath</span> <span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token operator">></span> <span class="token builtin">UICollectionViewCell</span> <span class="token punctuation">{</span> <span class="token keyword">let</span> cell <span class="token operator">=</span> collectionView <span class="token punctuation">.</span> <span class="token function">dequeueReusableCell</span> <span class="token punctuation">(</span> withReuseIdentifier <span class="token punctuation">:</span> <span class="token string">"Cell"</span> <span class="token punctuation">,</span> <span class="token keyword">for</span> <span class="token punctuation">:</span> indexPath <span class="token punctuation">)</span> cell <span class="token punctuation">.</span> contentView <span class="token punctuation">.</span> backgroundColor <span class="token operator">=</span> randomColors <span class="token punctuation">.</span> <span class="token function">randomElement</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> cell <span class="token punctuation">.</span> contentView <span class="token punctuation">.</span> cornerRadius <span class="token operator">=</span> <span class="token number">13</span> <span class="token keyword">return</span> cell <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Now I will create a CustomPageViewController including an array ColorViewController just created above in ViewController. I will initialize from within the code pageViewController because when dragging directly from the Storyboard, Swift will default to transitionStyle as .pageCurl.
1 2 3 4 5 6 7 8 9 10 | pageViewController <span class="token operator">=</span> <span class="token function">CustomPageViewController</span> <span class="token punctuation">(</span> transitionStyle <span class="token punctuation">:</span> <span class="token punctuation">.</span> scroll <span class="token punctuation">,</span> navigationOrientation <span class="token punctuation">:</span> <span class="token punctuation">.</span> horizontal <span class="token punctuation">,</span> options <span class="token punctuation">:</span> <span class="token constant">nil</span> <span class="token punctuation">)</span> pageViewController <span class="token punctuation">.</span> customDelegate <span class="token operator">=</span> <span class="token keyword">self</span> pageViewController <span class="token punctuation">.</span> controllers <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token function">ColorViewController</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> <span class="token function">ColorViewController</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> <span class="token function">ColorViewController</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">]</span> <span class="token function">addChild</span> <span class="token punctuation">(</span> pageViewController <span class="token punctuation">)</span> contentView <span class="token punctuation">.</span> <span class="token function">addSubview</span> <span class="token punctuation">(</span> pageViewController <span class="token punctuation">.</span> view <span class="token punctuation">)</span> pageViewController <span class="token punctuation">.</span> view <span class="token punctuation">.</span> snp <span class="token punctuation">.</span> makeConstraints <span class="token punctuation">{</span> $ <span class="token number">0</span> <span class="token punctuation">.</span> top <span class="token punctuation">.</span> leading <span class="token punctuation">.</span> <span class="token function">equalToSuperview</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">offset</span> <span class="token punctuation">(</span> <span class="token number">15</span> <span class="token punctuation">)</span> $ <span class="token number">0</span> <span class="token punctuation">.</span> trailing <span class="token punctuation">.</span> bottom <span class="token punctuation">.</span> <span class="token function">equalToSuperview</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">inset</span> <span class="token punctuation">(</span> <span class="token number">15</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> |
Next I will let ViewController conform CustomPageViewControllerDelegate
1 2 3 4 5 6 | <span class="token keyword">extension</span> <span class="token builtin">ViewController</span> <span class="token punctuation">:</span> <span class="token builtin">CustomPageViewControllerDelegate</span> <span class="token punctuation">{</span> <span class="token keyword">func</span> <span class="token function">pageViewController</span> <span class="token punctuation">(</span> pageViewController <span class="token punctuation">:</span> <span class="token builtin">CustomPageViewController</span> <span class="token punctuation">,</span> didUpdatePageIndex index <span class="token punctuation">:</span> <span class="token builtin">Int</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> pageLabel <span class="token punctuation">.</span> text <span class="token operator">=</span> <span class="token string">"Trang <span class="token interpolation"><span class="token delimiter variable">(</span> index <span class="token operator">+</span> <span class="token number">1</span> <span class="token delimiter variable">)</span></span> "</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Build and Run Project I will get the results as the example at the beginning of the post
Source Code
https://github.com/buixuanhuy5798/DemoCustomPageViewController