IOS

XX캠퍼스 강의 - ch05 _ NavigationController

Machine_웅 2022. 6. 7. 21:59
728x90
반응형

1. UINavigationController

content View Controller

- 화면을 구성하는 뷰를 직접 구현하고 관련된 이벤트를 처리하는 뷰 컨트롤러

- 일반적으로 스토리 생성시 생기는 컨트롤러로 보면 된다.

 

 

container View Controller 

- 하나 이상의 child View Controller 를 가지고 있다.

- 하나 이상의 child View Controller 를 관리하고 레이아웃과 화면 전환을 담당한다.

- 화면구성과 이벤트 관리는 child View Controller  에서 한다.

- container View Controller 는 대표적으로 Navigation Controller 와 TabBar Controller 가 있다.

 

 UINavigation Controller

- 계층구조로 구성된 content를 순차적으로 보여주는 container View Controller

- navigation stack 을 이용하여 뷰컨트롤러의 화면전환을  관리 ( last in first out )

 

https://daheenallwhite.github.io/ios/2019/07/25/Navigation-Controller/

 

[iOS] Navigation Controller - stack 구조로 계층적으로 화면 구현하기

Dana Daheen Lee<br>#iOS #Swift #CleanCode #Programming

daheenallwhite.github.io

 

2. 화면전환의 개념

 

- ViewController 의 view 위에 다른 view와 바꿔치기  ( 사용 하지 말아야 할 방법 - 메모리 누수 위험 ) 

 

- ViewController 에서 다른 ViewController 를 호출하여 전환

=> present 메소드 이용  ( 이동할 화면, 화면전환시 애니메이션 효과 여부, completion 클로저 )

=> dismiss 메소드로 이전화면으로 이동 ( 애니메이션 효과 적용 여부, completion 클로저 )

 

- Navigation Controller 를 사용하여 화면 전환하기

=> pushViewController 메소드를 이용 화면 이동 (새로운 화면 ,애니메이션 효과 적용 여부)

=> popViewController 메소드 이용하여 네비게이션 스텍에서 화면 제거   ( 애니메이션 효과 적용 여부)

 

- 화면 전환용 객체 세그웨이( Segueway) 를 사용하여 화면 전환하기 ( 스토리 보드만으로 화면이동을 지정 )

 

 

Action Segueway

- 출발점이 버튼 등인 경우  ( 트리거 이벤트가 있는 것들 ) 

show  - 기본

show detail - 화면 분할 (아이패드 ) 

Present Modally - 이전꺼를 덮으면서 화면 등작

Present As Popover - ( 아이패드 팝업 )

Custrom - 사용자정의 방식 

 

Manual Segueway

- 출발점이 뷰 컨트롤러 자체인경우 

 

3. ViewController Life Cycle

 

 

 

appearing - 뷰가 화면에 나타나는중

appeard - 뷰가 화면에서 나타난게 완료된상태

disappearing - 뷰가 화면에 사라지는중

disappeared - 뷰가 화면에서 사라진 상태 

 

 

 

 

 

 

 

 

 

 

 

viewDidLoad

- 뷰 컨트롤러의 모든 뷰들이 메모리에 로드되었을 때

- 메모리에 처음 로드될때 한번만 호출

- 보통 딱 한번만 호출될 행위들을 이 메소드 안에 정의

(뷰초기화 작업, 네트워크 호출)

 

viewWillAppear

- 뷰가 뷰 계층에 추가되고, 화면에 보이기 직전

- 다른뷰에 갔다가 오면 재호출

- 뷰와 관련된 추가적인 초기화 작업

 

viewDidAppear

- 뷰가 뷰 계층에 추가된 후 호출

- 뷰를 나타낼때 필요한 추가작업

( 애니메이션 시작 )

 

viewWillDidAppear

- 뷰가 뷰 계층에  사라지기전 호출

- 최종적으로 데이터를 저장 

viewDidAppear

- 뷰가 사라지는 것과 관련된 작업

 

https://zeddios.tistory.com/43

 

iOS ) View Controller의 생명주기(Life-Cycle)

안녕하세요! 오늘은 View Controller생명 주기에 대해 알아보겠습니다. iOS를 시작하려고 하거나, 배우고 있는 분들이라면 반드시 알아야 해요. 하나하나 제대로 알아봅시다 ㅎㅎ View Controller의 생명

zeddios.tistory.com

 

 

4.화면간 데이터 전달하는 방법

 

코드로 다음 화면에 값전달

1) 뷰컨트롤러를 이용해서 프로퍼티에 접근 하는 방법

    
    // 코드로 푸시 방법
    @IBAction func tabCodePushBtn(_ sender: UIButton) {
        
        guard let viewController = self.storyboard?.instantiateViewController(identifier: "CodePushViewController")as?
                CodePushViewController
        else {return}
        
        viewController.name = "Woong"
        self.navigationController?.pushViewController(viewController, animated: false)
    }
    
    // 코드로 프레젠트
    @IBAction func tabCodePresent(_ sender: UIButton) {
        
        guard let viewController = self.storyboard?.instantiateViewController(identifier: "CodePresentViewController")as? CodePresentViewController
              
        else{return}
        
        viewController.name = "Woongs"
        viewController.modalPresentationStyle = .fullScreen
        
        self.present(viewController, animated: true,completion: nil)
    }
    override func viewDidLoad() {
        super.viewDidLoad()

        if let name = name{
            self.nameLabel.text = name
            self.nameLabel.sizeToFit()
        }
      
    }

 

코드로 이전화면으로 값 전달

- 델리게이트 패턴 이용 ( 위임자자를 가지고 있는객체가 다른객체에 전달 해주는 역할 )

 

- view controller 

import UIKit



protocol SendDataDelegate: AnyObject{
    func sendData(name: String)
}


class CodePresentViewController: UIViewController {

    @IBOutlet weak var nameLabel: UILabel!
    
    var name: String?
    
    // weak 는 델리게이트 패턴사용시 델리게이트 변수앞에 붙여줘야 한다 ( 강한 순환 참조로 메모리릭이 발생가능성이 있음 )
    weak var deletgate : SendDataDelegate?
    
    
    override func viewDidLoad() {
        super.viewDidLoad()

        if let name = name{
            self.nameLabel.text = name
            self.nameLabel.sizeToFit()
        }
      
    }
    
    @IBAction func btnBack(_ sender: UIButton) {
        
        self.deletgate?.sendData(name: "Woongs")
        self.presentingViewController?.dismiss(animated: true, completion: nil)
    }
    
}

 

//
//  ViewController.swift
//  FastCampers_ScreenTransition
//
//  Created by Woong on 2022/06/07.
//

import UIKit

class ViewController: UIViewController, SendDataDelegate {
    
    @IBOutlet weak var nameLabel: UILabel!
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
    
    
    // 코드로 푸시 방법
    @IBAction func tabCodePushBtn(_ sender: UIButton) {
        
        guard let viewController = self.storyboard?.instantiateViewController(identifier: "CodePushViewController")as?
                CodePushViewController
        else {return}
        
        // 다음 화면에  값전달
        viewController.name = "Woong"
      
        self.navigationController?.pushViewController(viewController, animated: false)
    }
    
    // 코드로 프레젠트
    @IBAction func tabCodePresent(_ sender: UIButton) {
        
        guard let viewController = self.storyboard?.instantiateViewController(identifier: "CodePresentViewController")as? CodePresentViewController
              
        else{return}
        
        // 다음 화면에  값전달
        viewController.name = "Woongs"
        
        // 델리게이트를 위임 받음
        viewController.deletgate = self
        viewController.modalPresentationStyle = .fullScreen
        
        self.present(viewController, animated: true,completion: nil)
    }
    
    func sendData(name: String) {
        self.nameLabel.text = name
        self.nameLabel.sizeToFit()
        
    }
    
    
}

세그웨이로 다음화면에 전달하는 방법 

-  전처리 prepare 메서드를 이용한  사용방식 추천 

 

full 소스 

//
//  ViewController.swift
//  FastCampers_ScreenTransition
//
//  Created by Woong on 2022/06/07.
//

import UIKit

class ViewController: UIViewController, SendDataDelegate {
    
    @IBOutlet weak var nameLabel: UILabel!
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
    
    
    // 코드로 푸시 방법
    @IBAction func tabCodePushBtn(_ sender: UIButton) {
        
        guard let viewController = self.storyboard?.instantiateViewController(identifier: "CodePushViewController")as?
                CodePushViewController
        else {return}
        
        // 다음 화면에  값전달
        viewController.name = "Woong"
      
        self.navigationController?.pushViewController(viewController, animated: false)
    }
    
    // 코드로 프레젠트
    @IBAction func tabCodePresent(_ sender: UIButton) {
        
        guard let viewController = self.storyboard?.instantiateViewController(identifier: "CodePresentViewController")as? CodePresentViewController
              
        else{return}
        
        // 다음 화면에  값전달
        viewController.name = "Woongs"
        
        // 델리게이트를 위임 받음
        viewController.deletgate = self
        viewController.modalPresentationStyle = .fullScreen
        
        self.present(viewController, animated: true,completion: nil)
    }
    
    
    // 코드로  델리게이트로 처리하는 방식
    func sendData(name: String) {
        self.nameLabel.text = name
        self.nameLabel.sizeToFit()
        
    }
    
    
    // 세그웨이 방식으로 값 전달하는 방법
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        
        // 전환하려는 뷰컨트롤러의 인스턴스를 가지고 올수 있다.
        if let viewController = segue.destination as? SeguePushViewController{
            viewController.name = "woogs"
        }
        
    }
    
    
}
import UIKit

class SeguePresentViewController: UIViewController {
    
    var name: String?

    @IBOutlet weak var nameLabel: UILabel!
    override func viewDidLoad() {
        super.viewDidLoad()

    }

    @IBAction func backBtn(_ sender: UIButton) {
        
        self.presentingViewController?.dismiss(animated: true, completion: nil)
    }
    
}
import UIKit



protocol SendDataDelegate: AnyObject{
    func sendData(name: String)
}


class CodePresentViewController: UIViewController {

    @IBOutlet weak var nameLabel: UILabel!
    
    var name: String?
    
    // weak 는 델리게이트 패턴사용시 델리게이트 변수앞에 붙여줘야 한다 ( 강한 순환 참조로 메모리릭이 발생가능성이 있음 )
    weak var deletgate : SendDataDelegate?
    
    
    override func viewDidLoad() {
        super.viewDidLoad()

        if let name = name{
            self.nameLabel.text = name
            self.nameLabel.sizeToFit()
        }
      
    }
    
    @IBAction func btnBack(_ sender: UIButton) {
        
        self.deletgate?.sendData(name: "Woongs")
        self.presentingViewController?.dismiss(animated: true, completion: nil)
    }
    
}
import UIKit

class CodePushViewController: UIViewController {

    @IBOutlet weak var nameLabel: UILabel!
    
    var name: String?
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        
        if let name = name{
            self.nameLabel.text = name
            self.nameLabel.sizeToFit()
        }

    }
    

    @IBAction func btnBack(_ sender: UIButton) {
        self.navigationController?.popViewController(animated:true)
    }
    
}

5. 에셋 카탈로그 

 

 

728x90
반응형