Danny의 iOS 컨닝페이퍼
article thumbnail

 

코드로 작성 시 컴파일 시 메모리에 바로 올라갑니다.  
                —> 다음으로 스토리보드의 메모리 생성  
                —> 그다음 서로 연결시킨 후 viewDidLoad 호출.

 

화면이동 및 데이터 전달 방법

4가지 화면이동 방법과 5가지 데이터 전달방법을 소개하겠습니다.

 

화면이동

1. 코드로 직접 이동

2. 스토리보드로 뷰 컨트롤러만 만들고 화면이동

3. 스토리보드의 간접세그로 연결 후 화면이동 

4. 스토리보드의 직접세그로 연결 후 화면이동

 

데이터 전달방법

1. 직접 프로퍼티로 접근하여 전달

2. 세그를 통한 데이터 전달

3. 클로저를 통해 전달

4. 노티피케이션을 통한 전달

5. 델리게이트 패턴을 통한 전달

 

데이터 전달과 화면이동은 동시에 일어나니 서로 묶어서 설명드리겠습니다.

 

 

시작

오늘 해볼 것은 버튼을 누르면 텍스트필드의 데이터 전달하고

화면이동을 하는 앱을 만드려 보려고 합니다.

class ViewController: UIViewController {
    
    @IBOutlet weak var firstTextField: UITextField!
    @IBOutlet weak var secondTextField: UITextField!
    @IBOutlet weak var thirdTextField: UITextField!
    @IBOutlet weak var fourthTextField: UITextField!
    @IBOutlet weak var fifthTextField: UITextField!
    @IBOutlet weak var sixthTextField: UITextField!
    @IBOutlet weak var seventhTextField: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
    }
    
    @IBAction func nextButtonsTapped(_ sender: UIButton) {
        // Tag를 통해 버튼을 각각 작동되게 해놨습니다.
        switch sender.tag {
            
        }
    }
}

자세한 설명은 주석에도 적혀있습니다.

 

그리고 출력 결과는 마지막에 모아서 보여드리겠습니다.

(단순히 TextField의 내용이 전달되어 다음 컨트롤러에 나타납니다)

 

 

코드로 화면 이동 및 데이터 전달

프로퍼티를 통하여 데이터를 전달하도록 해보겠습니다.

 

일단은 FirstViewController를 코드로 만들어 줬습니다.

여기서 중요한 건 데이터를 저장하기 위해 변수를 만들어 줬다는 것입니다.

// MARK: - 코드로 프로퍼티를 통해 데이터 전달 및 화면이동
class FirstViewController: UIViewController {
    
    lazy var firstLable: UILabel = {
        let label = UILabel(frame: CGRect(x: self.view.frame.width/2-200,
                                          y: self.view.frame.height/2-25,
                                          width: 400, height: 50))
        label.textAlignment = .center
        label.font = .systemFont(ofSize: 24)
        return label
    }()
    
    // 데이터를 받기 위해 변수를 생성해줘야 합니다.
    var strData: String?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.addSubview(firstLable)
        self.view.backgroundColor = .white
        
        // 프로퍼티로 데이터를 받아와 label에 업데이트
        firstLable.text = strData ?? ""
    }
}

 

ViewController에서는 FirstVC객체를 생성을 해주고 

FirstVC에 생성해 둔 변수에다 현재 TextField의 값을 넣어줬습니다.

class ViewController: UIViewController {
    
    @IBOutlet weak var firstTextField: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func nextButtonsTapped(_ sender: UIButton) {
        switch sender.tag {
        
        // MARK: - 코드로 프로퍼티를 통해 데이터 전달 및 화면이동
        case 0:
            // FirstVC의 객체를 생성해줍니다.
            let firstVC = FirstViewController()
            // 현재 텍스트 필드에 적혀있는 텍스트를 FirstVC의 strData로 전달!
            firstVC.strData = firstTextField.text
            
            // 네이게이션의 push를 통한 화면이동!
            navigationController?.pushViewController(firstVC, animated: true)
            return
   
        default: break
        }
    }
}

 

 

스토리보드로 뷰 컨트롤러를 만들어 화면이동 및 데이터 전달

이와 같이 스토리보드에 UIViewController를 생성해 줬습니다.

 

어떻게 하면 화면이동 및 데이터 전달을 할 수 있을까요?

 

일단 스토리보드로 만들었기 때문에 접근하는 방식부터 코드방식이랑은 다릅니다.

제가 생각하기엔 화면 생성 및 이동 시 가장 간단한 방법이라고 생각합니다.

 

똑같이 프로퍼티로 데이터를 전달받을 예정이고

스토리보드를 사용해서 그런지 코드가 조금 더 간결해진 느낌입니다.

코드를 살펴봅시다.

 

SecondViewController

// MARK: - 스토리보드로 뷰 컨트롤러를 만들어 화면이동 및 데이터 전달
class SecondViewController: UIViewController {
    
    @IBOutlet weak var secondLabel: UILabel!
    
    // 데이터를 받기 위해 변수를 생성해줘야 합니다.
    var strData: String?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 받은 데이터를 label에 업데이트
        secondLabel.text = strData ?? ""
    }
}

 

위에서 스토리보드는 방식이 다르다고 했죠?

바로 Identifier추가해 줘야 되는데요.

 

추가 방법은

스토리보드에서 생성된 SecondViewController를 선택 후

Identifier 정해줘야 정상적으로 ViewController 호출이 가능해집니다!

 

storyboard의 instantiateViewController를 통해

ViewController로 접근이 가능합니다.

 

이제 SecondViewController로 접근이 가능해졌으니 데이터를 전달하고

push를 통하여 다음 화면으로 넘어갑시다. 

class ViewController: UIViewController {
    
    @IBOutlet weak var secondTextField: UITextField!
 
    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func nextButtonsTapped(_ sender: UIButton) {
        switch sender.tag {

        // MARK: - 스토리보드로 뷰 컨트롤러를 만들어 화면이동 및 데이터 전달
        case 1:
            // 정해준 스토리보드의 Identifier를 사용하여 ViewController를 불러와 줍시다.
            // 타입 캐스팅으로 UIViewController(구체적이지 않은 타입) -> SecondViewController 형변환을 해줘야 합니다.
            guard let secondVC = storyboard?.instantiateViewController(withIdentifier: "SecondVC") as? SecondViewController else { return }
            
            // 현재 텍스트 필드에 적혀있는 텍스트를 secondVC의 strData로 전달!
            secondVC.strData = secondTextField.text
            
            // 네이게이션의 push를 통한 화면 전환
            navigationController?.pushViewController(secondVC, animated: true)
            return
  
        default: break
        }
    }
}

 

 

스토리보드의 간접세그로 연결 후 화면이동 및 데이터 전달

이번에는 스토리보드에서 간접적으로 세그를 연결하는 작업을 해보겠습니다.

스토리보드에서 연결할 ViewController를 클릭 후 control + 드레그를 통해서 다음 뷰로 연결해 줍시다.

세그의 동작을 선택합니다. (내비게이션을 사용하므로 Show로 연결)

 

마찬가지로 스토리보드를 사용하므로 idnetifier을 정해줍시다.

 

직접 세그를 연결할 때는 2가지를 추가해줘야 합니다.

일단 prepare란 메서드를 통하여 다른 뷰컨트롤러로 접근이 가능합니다. 즉, 데이터를 전달할 수 있죠.

다음으로 performSegue메서드입니다. 이건 연결된 세그로 이동을 시켜주는 메서드이죠.

class ViewController: UIViewController {

    @IBOutlet weak var thirdTextField: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    // 세그웨이로 데이터를 전달하고 싶을땐 "prepare"함수를 이용해야 한다
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        
        // MARK: - 스토리보드의 간접세그로 연결 후 화면이동 및 데이터 전달
        if segue.identifier == "ThirdVC" {
            // UIViewController(구체적이지 않은 타입) --> ThirdViewController 타입 캐스팅
            let thirdVC = segue.destination as! ThirdViewController  // 종착지 설정
            
            // 현재 텍스트 필드에 적혀있는 텍스트를 thirdVC의 strData로 전달!
            thirdVC.strData = thirdTextField.text
        }
    }

    @IBAction func nextButtonsTapped(_ sender: UIButton) {
        switch sender.tag {

        // MARK: - 스토리보드의 간접세그로 연결 후 화면이동 및 데이터 전달
        case 2:
            // 화면을 이동하기 위해 performSegue를 불러준다.
            performSegue(withIdentifier: "ThirdVC", sender: self)
            return
               
        default: break
        }
    }
}

 

이번에도 프로퍼티로 데이터를 전달받기 때문에 이와 같이 다음 컨트롤러를 만들어 줬습니다.

// MARK: - 스토리보드의 간접세그로 연결 후 화면이동 및 데이터 전달
class ThirdViewController: UIViewController {
    
    @IBOutlet weak var thirdLabel: UILabel!
    
    // 데이터를 받기 위해 변수를 생성해줘야 합니다.
    var strData: String?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 받은 데이터를 label에 업데이트
        thirdLabel.text = strData ?? ""
    }
}

 

 

스토리보드의 직접세그로 연결 후 화면이동 및 데이터 전달

직접 세그란?

예를 들어 다음 화면으로 넘어가는 동작을 하는 버튼을 직접적으로 세그를 연결해 주는 것이다.

 

생성하는 방법은 간접세그랑 직접세그와 같으므로 스토리보드 설명은 넘어가겠습니다.

 

이제 코드를 살펴봅시다.

세그를 직접 연결해 줬기 때문에 버튼은 이미 이동에 필요한 동작은 준비된 상태입니다.

그러므로 performSegue(이동하는 코드)가 자동으로 호출되므로 필요가 없죠.

남은 데이터 전달을 위해 위와 같이 prepare를 사용해 봅시다.

class ViewController: UIViewController {

    @IBOutlet weak var fourthTextField: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    // 세그웨이로 데이터를 전달하고 싶을땐 "prepare"함수를 이용해야 한다
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        
        // MARK: - 스토리보드의 직접세그로 연결 후 화면이동 및 데이터 전달
        // 직접적으로 연결했기 때문에 간접 세그에서 연견한 방식인 performSegue 호출없이 사용가능
        if segue.identifier == "FourthVC" {
            // UIViewController(구체적이지 않은 타입) --> ThirdViewController 타입 캐스팅
            let fourthVC = segue.destination as! FourthViewController  // 종착지 설정
            
            // 현재 텍스트 필드에 적혀있는 텍스트를 fourthVC의 strData로 전달!
            fourthVC.strData = fourthTextField.text
        }
    }
}
// MARK: - 스토리보드의 직접세그로 연결 후 화면이동 및 데이터 전달
class FourthViewController: UIViewController {
    
    @IBOutlet weak var fourthLabel: UILabel!
    
    // 데이터를 받기 위해 변수를 생성해줘야 합니다.
    var strData: String?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 받은 데이터를 label에 업데이트
        fourthLabel.text = strData
    }
}

 

 

클로저로 데이터 전달

클로저는 이름 없는 함수.

저는 클로저를 어떠한 행동을 담을 수 있는 함수라고 생각하고 사용하고 있습니다.

 

보통 A -> B로 데이터를 전달하는 과정은

화면을 이동시킬 때 이미 이동할 객체에 대한 접근을 하고 있으므로

접근한 프로퍼티로 전달하는 것이 더 간단합니다.

 

B -> A로 컨트롤러를 전환 시, 클로저를 사용하여 데이터를 받아오고 행동을 정의해주고

A -> B로 이동은 직접 객체의 프로퍼티로 접근하여 데이터를 넘겨는 게 훨씬 간단하다.

 

간단히 예제를 설명하면

일단 A -> B는 프로퍼티로 접근해서 텍스트필드의 데이터를 전달하고 있습니다.

그 다음 클로저를 통해 B -> A 컨트롤러로 데이터를 전달하는 과정을 담고 있습니다.

 

코드를 보시죠.

 

이 코드는 A 컨트롤러 입니다.

class ViewController: UIViewController {
  
    @IBOutlet weak var fifthTextField: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    @IBAction func nextButtonsTapped(_ sender: UIButton) {
        switch sender.tag {
 
        // MARK: - 클로저로 데이터 전달
        // B -> A로 컨트롤러를 전환 시 클로저를 사용하여 데이터를 받아오고 행동을 정의함
        // A -> B 이동은 직접 객체의 프로퍼티로 접근하여 데이터를 넘겨는게 훨씬 간단하다.
        case 4:
            let fifthtVC = FifthViewController()
            // 현재 텍스트 필드에 적혀있는 텍스트를 FifthtVC의 strData로 전달!
            fifthtVC.strData = fifthTextField.text
            fifthtVC.modalPresentationStyle = .fullScreen
            present(fifthtVC, animated: true)
            
            // 클로저는 어떠한 행동과 데이터를 담아서 전달시키므로 이와같이 text 및 color도 변경 가능
            fifthtVC.closure = { text in
                self.fifthTextField.text = text
                self.fifthTextField.textColor = .red
            }
            return

        default: break
        }
    }
}

 

여기는 B 컨트롤러 코드 입니다.

 

클로저는 일종의 행동을 담는 함수라고 했습니다.

 

행동을 담은 클로저를 생성시켜 준 뒤

버튼을 누르면 "from ClosureVC"를 추가해 데이터를 전달하는 과정을 만들어봤습니다.

// MARK: - 클로저로 데이터 전달
class FifthViewController: UIViewController {
    
    lazy var fifthTextFiled: UITextField = {
        let tf = UITextField(frame: CGRect(x: self.view.frame.width/2-150,
                                          y: self.view.frame.height/2-20,
                                          width: 300, height: 40))
        tf.borderStyle = .roundedRect
        tf.textAlignment = .center
        tf.font = .systemFont(ofSize: 24)
        return tf
    }()
    
    lazy var fifthButton: UIButton = {
        let button = UIButton(frame: CGRect(x: self.view.frame.width/2-40,
                                          y: self.view.frame.height/2+40,
                                          width: 80, height: 50))
        button.setTitleColor(.systemBlue, for: .normal)
        button.setTitle("전달", for: .normal)
        button.addTarget(self, action: #selector(fifthButtonTapped), for: .touchUpInside)
        return button
    }()
    
    // 데이터를 받기 위해 변수를 생성해줘야 합니다.
    var strData: String?
    
    // String을 갖고 어떠한 행동을 담기위해 클로저를 생성
    var closure: ((String) -> Void)?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.addSubview(fifthTextFiled)
        self.view.addSubview(fifthButton)
        self.view.backgroundColor = .lightGray
        
        // (A -> B 전달) 프로퍼티로 데이터를 받아 label에 업데이트
        fifthTextFiled.text = strData ?? ""
    }
    
    
    @objc func fifthButtonTapped(_ sender: UIButton) {
        // 데이터의 전달 확인을 위해 문자 "from ClosureVC" 를 추가
        let text = "\(fifthTextFiled.text ?? "") from ClosureVC"
        
        // 클로저의 input부분에 데이터를 담아줍니다. (B -> A 전달)
        closure?(text)
        dismiss(animated: true)
    }
}

 

마지막으로 ViewController로 이동하여 전달한 데이터를 받고 행동을 추가해 주면 됩니다.

 

실행

 

 

노티피케이션 전달

다들 Notification을 방송국이라고 부르고 있습니다.

 

중요 메서드를 확인해 보자.

addObserver : 일종의 관측소다. post로 일을 지시받을 때까지 관찰을 하고 행동을 정의해 줍니다.

post : 데이터와 함께 관측소로 발송시킨다. (이 시점에 관측소에 저장된 동작을 실행하죠.)

 

여기서도 B -> A로 데이터를 전달하는 방식의 구현으로 했습니다.

왜냐하면 addObserver 관측소가 먼저 실행이 돼있어야 post를 받아 작업을 실행할 수 있는데,

만약 A -> B 실행을 하게 되면 아직 B 컨트롤러의 객체가 실행이 안 돼있으므로 노티피케이션을 사용할 수 없다.

 

코드를 봅시다.

class ViewController: UIViewController {

    @IBOutlet weak var sixthTextField: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func nextButtonsTapped(_ sender: UIButton) {
        switch sender.tag {
            
        // MARK: - 노티피케이션 전달
        case 5:
            let sixthVC = SixthViewController()
            sixthVC.strData = sixthTextField.text ?? ""
            sixthVC.modalPresentationStyle = .fullScreen
            // addObserver는 일종에 관제소다.
            // Post로 알람이 오게 되면 관제소에서 관측을하여 받은 데이터를 갖고 notificationButtonTapped을 통해 작업을 수행시킨다.
            // 즉, 관측소에서 알람을 받으면 정의된 함수를 실행 시켜줌.
            NotificationCenter.default.addObserver(self, selector: #selector(notificationButtonTapped(_:)), name: NSNotification.Name("Notification"), object: nil)
            
            present(sixthVC, animated: true)
            
        default: break
        }
    }
    
    // #selector 관제소에서 post를 관측 시 이 동작들을 실행시킨다.
    @objc func notificationButtonTapped(_ notification: Notification) {
        let notificationData = notification.object as? String
        
        sixthTextField.text = notificationData
        sixthTextField.textColor = .red
    }
}

 

발송 시점은 버튼을 누를 때 발송이 된다.

// MARK: - 노티피케이션 전달
class SixthViewController: UIViewController {
    
    lazy var sixthTextFiled: UITextField = {
        let tf = UITextField(frame: CGRect(x: self.view.frame.width/2-150,
                                          y: self.view.frame.height/2-20,
                                          width: 300, height: 40))
        tf.borderStyle = .roundedRect
        tf.textAlignment = .center
        tf.font = .systemFont(ofSize: 24)
        return tf
    }()
    
    lazy var sixthButton: UIButton = {
        let button = UIButton(frame: CGRect(x: self.view.frame.width/2-40,
                                          y: self.view.frame.height/2+40,
                                          width: 80, height: 50))
        button.setTitleColor(.systemBlue, for: .normal)
        button.setTitle("전달", for: .normal)
        button.addTarget(self, action: #selector(sixthButtonTapped), for: .touchUpInside)
        return button
    }()
    
    // 데이터를 받기 위해 변수를 생성해줘야 합니다.
    var strData: String?
        
    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.addSubview(sixthTextFiled)
        self.view.addSubview(sixthButton)
        self.view.backgroundColor = .lightGray
        
        // (A -> B 전달) 프로퍼티로 데이터를 받아 label에 업데이트
        sixthTextFiled.text = strData ?? ""
    }
    
    @objc func sixthButtonTapped(_ sender: UIButton) {
        // 데이터의 전달 확인을 위해 문자 "from Notication" 를 추가
        let text = "\(sixthTextFiled.text ?? "") from Notication"

        // 노티피케이션 Post는 데이터를 추가할 수 있고 알람을 보낸다.
        // 알람을 보내서 작업을 수행하라고 지시하는 시점이다.
        NotificationCenter.default.post(name: Notification.Name("Notification"), object: text)
        
        dismiss(animated: true)
    }
}

 

결과

 

 

델리게이트 전달

자세한 설명은 여기를 참고하세요

Custom delegate 패턴

 

코드만 첨부하겠습니다.

class ViewController: UIViewController, SevenViewControllerDelegate {

    @IBOutlet weak var seventhTextField: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func nextButtonsTapped(_ sender: UIButton) {
        switch sender.tag {
      
        // MARK: - 델리게이트 전달
        case 6:
            let seventhVC = SeventhViewController()
            seventhVC.strData = seventhTextField.text ?? ""
            seventhVC.modalPresentationStyle = .fullScreen
            // ⭐️ 대리자를 현재 뷰컨트롤러로 지정해줍니다.
            seventhVC.delegate = self
            
            present(seventhVC, animated: true)
        default: break
        }
    }
 
    // 델리게이트 실행 시 데이터를 갖고 작업을 수행
    func getTextFieldData(_ viewController: SeventhViewController, data: String) {
        seventhTextField.text = data
        seventhTextField.textColor = .red
    }
}

 

SeventhViewController 코드

// MARK: - 델리게이트 전달
// 프로토콜을 동작을 정의할 함수와 함께 만들어 줍니다.
protocol SevenViewControllerDelegate: AnyObject {
    func getTextFieldData(_ viewController: SeventhViewController, data: String)
}

class SeventhViewController: UIViewController {

    lazy var sevnethTextFiled: UITextField = {
        let tf = UITextField(frame: CGRect(x: self.view.frame.width/2-150,
                                          y: self.view.frame.height/2-20,
                                          width: 300, height: 40))
        tf.borderStyle = .roundedRect
        tf.textAlignment = .center
        tf.font = .systemFont(ofSize: 24)
        return tf
    }()
    
    lazy var sevnethButton: UIButton = {
        let button = UIButton(frame: CGRect(x: self.view.frame.width/2-40,
                                          y: self.view.frame.height/2+40,
                                          width: 80, height: 50))
        button.setTitleColor(.systemBlue, for: .normal)
        button.setTitle("전달", for: .normal)
        button.addTarget(self, action: #selector(sixthButtonTapped), for: .touchUpInside)
        return button
    }()
    
    // 데이터를 받기 위해 변수를 생성해줘야 합니다.
    var strData: String?
    
    // 델리게이트로 변수를 만들어 줍니다.
    var delegate: SevenViewControllerDelegate?
        
    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.addSubview(sevnethTextFiled)
        self.view.addSubview(sevnethButton)
        self.view.backgroundColor = .lightGray
        
        // (A -> B 전달) 프로퍼티로 데이터를 받아 label에 업데이트
        sevnethTextFiled.text = strData ?? ""
    }
    
    @objc func sixthButtonTapped(_ sender: UIButton) {
        // 데이터의 전달 확인을 위해 문자 "from Delegate"" 를 추가
        let text = "\(sevnethTextFiled.text ?? "") from Delegate"
        
        // 텍스트를 갖고 데이터를 전담합니다.
        self.delegate?.getTextFieldData(self, data: text)
        dismiss(animated: true)
    }
}

 

결과

 

 

전체 코드

각각의 뷰컨트롤러 코드는 위를 확인해 주세요.

class ViewController: UIViewController, SevenViewControllerDelegate {
    
    @IBOutlet weak var firstTextField: UITextField!
    @IBOutlet weak var secondTextField: UITextField!
    @IBOutlet weak var thirdTextField: UITextField!
    @IBOutlet weak var fourthTextField: UITextField!
    @IBOutlet weak var fifthTextField: UITextField!
    @IBOutlet weak var sixthTextField: UITextField!
    @IBOutlet weak var seventhTextField: UITextField!
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
    
    // 세그웨이로 데이터를 전달하고 싶을땐 "prepare"함수를 이용해야 한다
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        
        // MARK: - 스토리보드의 간접세그로 연결 후 화면이동 및 데이터 전달
        if segue.identifier == "ThirdVC" {
            // UIViewController(구체적이지 않은 타입) --> ThirdViewController 타입 캐스팅
            let thirdVC = segue.destination as! ThirdViewController  // 종착지 설정
            
            // 현재 텍스트 필드에 적혀있는 텍스트를 thirdVC의 strData로 전달!
            thirdVC.strData = thirdTextField.text
            
        // MARK: - 스토리보드의 직접세그로 연결 후 화면이동 및 데이터 전달
        // 직접적으로 연결했기 때문에 간접 세그에서 연견한 방식인 performSegue 호출없이 사용가능
        } else if segue.identifier == "FourthVC" {
            // UIViewController(구체적이지 않은 타입) --> ThirdViewController 타입 캐스팅
            let fourthVC = segue.destination as! FourthViewController  // 종착지 설정
            
            // 현재 텍스트 필드에 적혀있는 텍스트를 fourthVC의 strData로 전달!
            fourthVC.strData = fourthTextField.text
        }
    }
    
    @IBAction func nextButtonsTapped(_ sender: UIButton) {
        switch sender.tag {
            
        // MARK: - 코드로 프로퍼티를 통해 데이터 전달 및 화면이동
        case 0:
            // FirstVC의 객체를 생성해줍니다.
            let firstVC = FirstViewController()
            // 현재 텍스트 필드에 적혀있는 텍스트를 FirstVC의 strData로 전달!
            firstVC.strData = firstTextField.text
            
            // 네이게이션의 push를 통한 화면 전환
            navigationController?.pushViewController(firstVC, animated: true)
            return
            
        // MARK: - 스토리보드로 뷰 컨트롤러를 만들어 화면이동 및 데이터 전달
        case 1:
            // 정해준 스토리보드의 Identifier를 사용하여 ViewController를 불러와 줍시다.
            // 타입 캐스팅으로 UIViewController(구체적이지 않은 타입) -> SecondViewController 형변환을 해줘야 합니다.
            guard let secondVC = storyboard?.instantiateViewController(withIdentifier: "SecondVC") as? SecondViewController else { return }
            
            // 현재 텍스트 필드에 적혀있는 텍스트를 secondVC의 strData로 전달!
            secondVC.strData = secondTextField.text
            
            // 네이게이션의 push를 통한 화면 전환
            navigationController?.pushViewController(secondVC, animated: true)
            return
            
        // MARK: - 스토리보드의 간접세그로 연결 후 화면이동 및 데이터 전달
        case 2:
            // 화면을 이동하기 위해 performSegue를 불러준다.
            performSegue(withIdentifier: "ThirdVC", sender: self)
            return

        // MARK: - 클로저로 데이터 전달
        // B -> A로 컨트롤러를 전환 시 클로저를 사용하여 데이터를 받아오고 행동을 정의함
        // A -> B 이동은 직접 객체의 프로퍼티로 접근하여 데이터를 넘겨는게 훨씬 간단하다.
        case 4:
            let fifthtVC = FifthViewController()
            // 현재 텍스트 필드에 적혀있는 텍스트를 FifthtVC의 strData로 전달!
            fifthtVC.strData = fifthTextField.text
            fifthtVC.modalPresentationStyle = .fullScreen
            present(fifthtVC, animated: true)
            
            // 클로저는 어떠한 행동과 데이터를 담아서 전달시키므로 이와같이 text 및 color도 변경 가능
            fifthtVC.closure = { text in
                self.fifthTextField.text = text
                self.fifthTextField.textColor = .red
            }
            return
            
        // MARK: - 노티피케이션 전달
        case 5:
            let sixthVC = SixthViewController()
            sixthVC.strData = sixthTextField.text ?? ""
            sixthVC.modalPresentationStyle = .fullScreen
            // addObserver는 일종에 관제소다.
            // Post로 알람이 오게 되면 관제소에서 관측을하여 받은 데이터를 갖고 notificationButtonTapped을 통해 작업을 수행시킨다.
            // 즉, 관측소에서 알람을 받으면 정의된 함수를 실행 시켜줌.
            NotificationCenter.default.addObserver(self, selector: #selector(notificationButtonTapped(_:)), name: NSNotification.Name("Notification"), object: nil)
            
            present(sixthVC, animated: true)
        
        // MARK: - 델리게이트 전달
        case 6:
            let seventhVC = SeventhViewController()
            seventhVC.strData = seventhTextField.text ?? ""
            seventhVC.modalPresentationStyle = .fullScreen
            // ⭐️ 대리자를 현재 뷰컨트롤러로 지정해줍니다.
            seventhVC.delegate = self
            
            present(seventhVC, animated: true)
        default: break
        }
    }
    
    // #selector로 관제소에서 post를 관측 시 이 동작을 실행시킨다.
    @objc func notificationButtonTapped(_ notification: Notification) {
        let notificationData = notification.object as? String
        
        sixthTextField.text = notificationData
        sixthTextField.textColor = .red
    }
    
    // 델리게이트 실행 시 데이터를 갖고 작업을 수행
    func getTextFieldData(_ viewController: SeventhViewController, data: String) {
        seventhTextField.text = data
        seventhTextField.textColor = .red
    }
}

 

 

부족한 설명이지만, 조금은 이해 가셨나요?

틀린 내용이 있다면 언제든지 지적해 주시면 감사히 받겠습니다. 🫠
읽어주셔서 감사합니다 😃

 

 

반응형
profile

Danny의 iOS 컨닝페이퍼

@Danny's iOS

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!