{"id":20564060,"url":"https://github.com/clintjang/sample-swift-containerview","last_synced_at":"2025-04-14T15:10:08.471Z","repository":{"id":99120091,"uuid":"142840950","full_name":"ClintJang/sample-swift-containerview","owner":"ClintJang","description":"UIViewController 하위에 Container View를 이용하여 Controller를 작동(연결) 하는 셈플 소스입니다.","archived":false,"fork":false,"pushed_at":"2019-02-28T22:59:10.000Z","size":1611,"stargazers_count":18,"open_issues_count":0,"forks_count":5,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-14T15:09:58.779Z","etag":null,"topics":["addchildviewcontroller","containerview","containerviewcontroller","example","example-project","removefromparentviewcontroller","sample","sample-app","swift","uiviewcontroller"],"latest_commit_sha":null,"homepage":null,"language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ClintJang.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-07-30T07:31:24.000Z","updated_at":"2024-07-19T07:48:17.000Z","dependencies_parsed_at":"2023-03-13T15:51:56.017Z","dependency_job_id":null,"html_url":"https://github.com/ClintJang/sample-swift-containerview","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ClintJang%2Fsample-swift-containerview","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ClintJang%2Fsample-swift-containerview/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ClintJang%2Fsample-swift-containerview/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ClintJang%2Fsample-swift-containerview/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ClintJang","download_url":"https://codeload.github.com/ClintJang/sample-swift-containerview/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248904640,"owners_count":21180835,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["addchildviewcontroller","containerview","containerviewcontroller","example","example-project","removefromparentviewcontroller","sample","sample-app","swift","uiviewcontroller"],"created_at":"2024-11-16T04:23:41.383Z","updated_at":"2025-04-14T15:10:08.450Z","avatar_url":"https://github.com/ClintJang.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Sample Swift ContainerView\n\u003e UIViewController 하위에 Container View를 이용하여 Controller를 작동(연결) 할 수 있습니다.  \u003cbr /\u003e\n그것을 스토리보드와 코드를 이용해서 스크롤뷰 안에 들어가는 뷰들을 Container View로 넣어서 셈플링한 소스 입니다. \u003cbr /\u003e\nContainer View 1,2는 스토리보드로, \u003cbr /\u003e\nContainer View 3은 코드로 추가했습니다. 3은 제거하는 기능까지 테스트 했습니다.\n\n## 주요 설명\n[![License](http://img.shields.io/badge/License-MIT-green.svg?style=flat)](https://github.com/clintjang/sample-ios-timer/blob/master/LICENSE) [![Swift 4](https://img.shields.io/badge/swift-4.1-orange.svg?style=flat)](https://swift.org) \n- 스크롤뷰 안의 스크롤뷰의 내부 컨텐츠를 담는 뷰를 크게 만들고 그 안에 페이지 단위 View 들 안에 Container View 를 담았습니다.\n- 현재의 뷰 안에 컨트롤러를 연결 시킨 것과 다른 스토리보드의 파일을 링크 시킨 두가지 경우로 셈플링 하였습니다.\n\n## 스토리보드 이미지\n\u003cimg width=\"628\" height=\"631\" src=\"/Image/image_storyboard_00.png\"\u003e\u003c/img\u003e\n\n## 실행 이미지 (GIF)\n\u003cimg width=\"268\" height=\"480\" src=\"/Image/resultForImage.gif\"\u003e\u003c/img\u003e\n\n## 실행 결과 계층 구조\n- Container View 1,2를 스토리보드로 추가한 계층\n\u003cbr /\u003e\u003cimg width=\"517\" height=\"494\" src=\"/Image/image_result_hierarchy00.png\"\u003e\u003c/img\u003e\u003cbr /\u003e\n- Container View 3을 버튼을 눌러 코드로 추가한 계층\n\u003cbr /\u003e\u003cimg width=\"482\" height=\"499\" src=\"/Image/image_result_hierarchy01.png\"\u003e\u003c/img\u003e\u003cbr /\u003e\n\n## 결과 소스 및 파일\n\u003e 실제 받아서 실행해 보셔요~\n\n- Main.storyboard : 여기에 기본 베이스 화면을 구성했습니다.\n- Other.storyboard : 오른쪽의 두번째 Container View에 들어갈 RightViewController가 들어있습니다. (Container View 2)\n- ViewController.swift : 가로 길이가 디바이스에 따라 변하게 하였고, 스크롤뷰의 이벤트 받는 부분을 살짝 추가해봤습니다. \n\n```swift \nclass ViewController: UIViewController {\n\n    @IBOutlet weak var scrollViewContainerViewWidth: NSLayoutConstraint!\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        \n        // Setting the ContainerView's width size for the ScrollView\n        scrollViewContainerViewWidth.constant = UIScreen.main.bounds.size.width * 2\n    }\n    \n    // addChildController\n    @IBAction func onAddChildController(_ sender: Any) {\n        let storyboard = UIStoryboard(name: \"Other\", bundle: nil)\n        let addViewController = storyboard.instantiateViewController(withIdentifier: \"AddViewController\")\n        // if Constraints\n//        addViewController.view.translatesAutoresizingMaskIntoConstraints = false\n        \n        self.addChild(addViewController)\n        self.view.addSubview(addViewController.view)\n        \n        // if Constraints\n//        self.view.addConstraints(addViewController.view.constraints)\n        \n        addViewController.didMove(toParent: self)\n    }\n}\n\nextension ViewController: UIScrollViewDelegate {\n    func scrollViewDidScroll(_ scrollView: UIScrollView) {\n        print(\"Current X,Y are X:\\(scrollView.contentOffset.x), Y: \\(scrollView.contentOffset.y)\")\n        let currentPage = Int(round(scrollView.contentOffset.x / scrollView.frame.size.width))\n        print(\"current page : \\(currentPage)\")\n    }\n}\n```\n\n- LeftViewController.swift : 배경 컬러만 확인을 위해 수정했습니다.\n\t- StoryBoard로 추가한 케이스 입니다.\n\t- RightViewController.swift는 배경 색상만 달라서 별도 소스는 추가 안했습니다. \n\t\n```swift\nclass LeftViewController: UIViewController {\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        \n        // TEST backgroundColor\n        view.backgroundColor = #colorLiteral(red: 0.4666666687, green: 0.7647058964, blue: 0.2666666806, alpha: 1)\n    }\n    \n    // willMove -\u003e It appears on the parent screen.\n    override func willMove(toParent parent: UIViewController?) {\n        print(#function)\n        if let `parent` = parent as UIViewController? {\n            print(parent)   // TestScrollViewAndContainerView.ViewController\n        }\n    }\n    \n    // It appears on the parent screen. -\u003e didMove\n    override func didMove(toParent parent: UIViewController?) {\n        print(#function)\n        if let `parent` = parent as UIViewController? {\n            print(parent)\n        }\n    }\n}\n```\n\n- AddViewController.swift : 코드 레벨로 Contrainer View를 추가했습니다. \n\n```swift\nclass AddViewController: UIViewController {\n    deinit {\n        // check remove self\n        print(#function)\n    }\n    \n    override func viewDidLoad() {\n        super.viewDidLoad()\n        \n        // TEST backgroundColor\n        view.backgroundColor = #colorLiteral(red: 0.9098039269, green: 0.4784313738, blue: 0.6431372762, alpha: 1)\n    }\n    \n    // willMove -\u003e It appears on the parent screen.\n    override func willMove(toParent parent: UIViewController?) {\n        print(#function)\n        if let `parent` = parent as UIViewController? {\n            print(parent)\n        }\n    }\n    \n    // It appears on the parent screen. -\u003e didMove\n    override func didMove(toParent parent: UIViewController?) {\n        print(#function)\n        if let `parent` = parent as UIViewController? {\n            print(parent)\n        }\n    }\n    \n    // remove child view controller\n    @IBAction func onRemoveChildViewController(_ sender: Any) {\n        // Notify the parent to remove it by calling willMove.\n        // willMove 를 호출해서 제거한다는 것을 알립니다.\n        self.willMove(toParent: nil)\n        // Remove Constraint.\n        // 제약사항 제거\n        self.view.removeFromSuperview()\n        // Remove the relationship of the child connected to the parent.\n        // 부모에 연결된 자식의 관계를 제거합니다.\n        self.removeFromParent()\n    }\n}\n```\n\n## 추가 설명\n- 단순하게 addSubView를 하면 부모자식관계는 성립하지 않습니다.\n- addChildViewController를 이용해서 자식 컨트롤러를 추가합니다.\n- 추가 완료된 이후에는 부모컨트롤러에서 didMove:를 호출해 줘야 합니다.\n- removeFromParentViewController를 이용해서 자식 컨트롤러를 제거합니다.\n- 제거 순서는 자식의 부모 뷰를 Container View 계층에서 제거한 후, 자식과 부모는 Container View Controller와 연결을 끊어야 합니다.\n- 자식 컨트롤러가 오토레이아웃 환경인 경우 translatesAutoresizingMaskIntoConstraints 설정도 신경씁니다.\n\n\n## 링크\n- [Implementing a Container View Controller](https://developer.apple.com/documentation/uikit/uiviewcontroller) : 여기에서 Implementing a Container View Controller 부분에 설명이 되어있습니다.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclintjang%2Fsample-swift-containerview","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fclintjang%2Fsample-swift-containerview","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclintjang%2Fsample-swift-containerview/lists"}