{"id":152,"date":"2025-10-09T09:08:26","date_gmt":"2025-10-09T00:08:26","guid":{"rendered":"https:\/\/devserver.kr\/blog\/?p=152"},"modified":"2025-10-09T09:08:26","modified_gmt":"2025-10-09T00:08:26","slug":"ios-uipageviewcontroller","status":"publish","type":"post","link":"https:\/\/devserver.kr\/blog\/ios\/ios-uipageviewcontroller\/","title":{"rendered":"iOS UIPageViewController"},"content":{"rendered":"\n<div class=\"wp-block-jetpack-markdown\"><pre><code class=\"language-swift\">import UIKit\n\nclass NestVC: UIViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {\n    \n    let pageViewController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)\n\/*\n    let pageControl:UIPageControl = {\n        let pc = UIPageControl()\n        pc.currentPageIndicatorTintColor = .red\n        pc.pageIndicatorTintColor = .blue\n        pc.translatesAutoresizingMaskIntoConstraints = false\n        return pc\n    }()\n    *\/\n    var vcs = [UIViewController]()\n    \n    \n    override func viewDidLoad() {\n        super.viewDidLoad()\n\n        \/\/ Do any additional setup after loading the view.\n        setPageViewController()\n        \/\/setPageControl()\n    }\n    \n    func setPageViewController() {\n        pageViewController.dataSource = self\n        pageViewController.delegate = self\n        \n        let storyboard = UIStoryboard(name: &quot;Main&quot;, bundle: nil)\n        let vc1 = storyboard.instantiateViewController(withIdentifier: &quot;SB_NAV_MODE1&quot;) as! UINavigationController\n        \n        let vc2 = storyboard.instantiateViewController(withIdentifier: &quot;SB_NAV_MODE2&quot;) as! UINavigationController\n        \n        pageViewController.setViewControllers([vc1], direction: .forward, animated: true, completion: nil)\n        \n        vcs.append(vc1)\n        vcs.append(vc2)\n        \n        addChild(pageViewController)\n        view.addSubview(pageViewController.view)\n        pageViewController.didMove(toParent: self)\n        \n        \n    }\n    \/*\n    func setPageControl() {\n        pageControl.numberOfPages = 2\n        \n        view.addSubview(pageControl)\n        NSLayoutConstraint.activate([\n            pageControl.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0),\n            pageControl.leadingAnchor.constraint(equalTo: view.leadingAnchor),\n            pageControl.trailingAnchor.constraint(equalTo: view.trailingAnchor)\n        ])\n    }\n    *\/\n    \/*\n    \/\/ MARK: - Navigation\n\n    \/\/ In a storyboard-based application, you will often want to do a little preparation before navigation\n    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {\n        \/\/ Get the new view controller using segue.destination.\n        \/\/ Pass the selected object to the new view controller.\n    }\n    *\/\n\n    \/\/ MARK: - PageViewController\n    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -&gt; UIViewController? {\n        \n        guard let index = vcs.firstIndex(of: viewController) else {\n            return nil\n        }\n        \n        let prevIndex = index - 1\n        \n        guard prevIndex &gt;= 0 else {\n            return nil \/\/ vcs.last\n        }\n        \n        guard vcs.count &gt; prevIndex else {\n            return nil\n        }\n        \n        return vcs[prevIndex]\n        \n    }\n    \n    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -&gt; UIViewController? {\n        \n        guard let index = vcs.firstIndex(of: viewController) else {\n            return nil\n        }\n        \n        let nextIndex = index + 1\n        \n        guard nextIndex &lt; vcs.count else {\n            return nil \/\/ or vcs.first\n        }\n        \n        return vcs[nextIndex]\n    }\n    \n    func presentationCount(for pageViewController:UIPageViewController) -&gt; Int {\n        return vcs.count\n    }\n    \n    func presentationIndex(for pageViewController: UIPageViewController) -&gt; Int {\n        guard let firstViewController = vcs.first, let firstViewControllerIndex = vcs.firstIndex(of: firstViewController) else {\n            return 0\n        }\n        \n        return firstViewControllerIndex\n    }\n    \n    \/\/  \uc2a4\uc640\uc774\ud504 \uc81c\uc2a4\uccd0\uac00 \ub05d\ub098\uba74 \ud638\ucd9c\ub418\ub294 \uba54\uc11c\ub4dc\uc785\ub2c8\ub2e4. \uc5ec\uae30\uc11c \ud398\uc774\uc9c0 \ucee8\ud2b8\ub864\uc758 \uc778\ub514\ucf00\uc774\ud130\ub97c \uc6c0\uc9c1\uc5ec\uc904\uaebc\uc5d0\uc694\n    func pageViewController(_ pageViewController: UIPageViewController,\n                            didFinishAnimating finished: Bool,\n                            previousViewControllers: [UIViewController],\n                            transitionCompleted completed: Bool\n    ) {\n        \/\/  \ud398\uc774\uc9c0 \uc774\ub3d9\uc774 \uc548\ub410\uc73c\uba74 \uadf8\ub0e5 \uc885\ub8cc\n        guard completed else { return }\n        \n        \/\/  \ud398\uc774\uc9c0 \uc774\ub3d9\uc774 \ub410\uae30 \ub54c\ubb38\uc5d0 \ud398\uc774\uc9c0 \ucee8\ud2b8\ub864\uc758 \uc778\ub514\ucf00\uc774\ud130\ub97c \uac31\uc2e0\ud574\uc90d\uc2dc\ub2e4\n        \/*\n        if let vc = pageViewController.viewControllers?.first {\n            pageControl.currentPage = vc.view.tag\n        }\n *\/\n    }\n}\n\n<\/code><\/pre>\n<\/div>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[4,7],"tags":[],"class_list":["post-152","post","type-post","status-publish","format-standard","hentry","category-ios","category-swift"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/devserver.kr\/blog\/wp-json\/wp\/v2\/posts\/152","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devserver.kr\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devserver.kr\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devserver.kr\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/devserver.kr\/blog\/wp-json\/wp\/v2\/comments?post=152"}],"version-history":[{"count":1,"href":"https:\/\/devserver.kr\/blog\/wp-json\/wp\/v2\/posts\/152\/revisions"}],"predecessor-version":[{"id":153,"href":"https:\/\/devserver.kr\/blog\/wp-json\/wp\/v2\/posts\/152\/revisions\/153"}],"wp:attachment":[{"href":"https:\/\/devserver.kr\/blog\/wp-json\/wp\/v2\/media?parent=152"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devserver.kr\/blog\/wp-json\/wp\/v2\/categories?post=152"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devserver.kr\/blog\/wp-json\/wp\/v2\/tags?post=152"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}