[Do it!] 네비게이션 컨트롤러 앱

CoCoral·2023년 10월 20일
1

Do it!

목록 보기
16/25
post-thumbnail

Do it! 스위프트로 아이폰 앱 만들기
11장 네비게이션 컨트롤러 이용해 화면 전환하기

📱 실행 화면 📱


💻 Step 1. 네비게이션 컨트롤러 추가하기

  • 아이폰 화면 전체를 클릭한 후 메뉴에서
    Editor -> Embed in -> Navigation Controller 선택하기
  • 뷰 컨트롤러의 타이틀 변경하기

💻 Step 2. 뷰 추가하고 바 버튼으로 뷰 전환하기

  • Library 에서 View Controller 를 찾아 메인화면 컨트롤러 오른쪽에 놓기
  • Library 에서 Bar Button Item 을 찾아 메인화면 컨트롤러의 네비게이션 바 오른쪽에 놓기
  • Bar Button Item 을 우클릭 드래그하여 오른쪽의 뷰 컨트롤러에 갖다 놓고 Action Segue 의 Show 선택하기
  • 생성된 세그웨이의 Identifier 를 editBarbutton 으로 수정하기

💻 Step 3. 버튼 활용해 뷰 전환하기

  • 메인화면 컨트롤러에 [수정] 버튼 추가하기
  • 수정화면 컨트롤러에 레이블과 [완료] 버튼 추가하기
  • [수정] 버튼을 우클릭 드래그하여 수정화면 컨트롤러에 갖다 놓고 Action Segue 의 Show 선택하기
  • 생성된 세그웨이의 Identifier 를 editButton 으로 수정하기

  • 수정화면 컨트롤러를 위한 소스 파일 추가하기
    * File -> New -> File... -> iOS -> Source -> Cocoa Touch Class
  • 수정화면 컨트롤러의 Class 를 EditViewController 로 변경하기

  • 레이블에 대한 아웃렛 변수, [완료] 버튼에 대한 액션 함수 추가하기

var textWayValue: String = ""

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

        // Do any additional setup after loading the view.
        lblWay.text = textWayValue
    }
        
    @IBAction func btnDone(_ sender: UIButton) {
        _ = navigationController?.popViewController(animated: true)
    }
  • EditViewController 소스 파일을 다음과 같이 수정하기
  • 뷰 전환에 사용된 세그웨이 종류를 레이블에 출력하기 위함이다.
  • [완료] 버튼을 클릭하면 메인화면으로 이동한다.

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        let editViewController = segue.destination as! EditViewController
        if segue.identifier == "editButton" {
            editViewController.textWayValue = "segue : use button"
        }
        else if segue.identifier == "editBarButton" {
            editViewController.textWayValue = "segue : use Bar Button"
        }
    }
  • ViewController 소스 파일에 해당 코드 추가하기
    💡 prepare 함수: 세그웨이가 해당 뷰 컨트롤러로 전환되기 직전에 호출되는 함수로 데이터 전달을 위해 사용된다.
  • 세그웨이 종류에 따라 EditViewController 에게 다른 데이터 값을 전달한다.

💻 Step 3. 뷰 전환과 함께 메시지 전달하기

  • 메인화면과 수정화면에 메시지 전달을 위한 레이블과 텍스트필드 배치하기
  • 각 텍스트필드에 대한 아웃렛 변수 추가하기

import UIKit

//추가 코드
protocol EditDelegate {
    func didMessageEditDone(_ controller: EditViewController, message: String)
}

class EditViewController: UIViewController {
    var textWayValue: String = ""
    
    //추가 코드
    var textMessage: String = ""
    var delegate: EditDelegate?

    @IBOutlet var txMessage: UITextField!
    @IBOutlet var lblWay: UILabel!
    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        lblWay.text = textWayValue
        
        //추가 코드
        txMessage.text = textMessage
    }
        
    @IBAction func btnDone(_ sender: UIButton) {
        //추가 코드
        if delegate != nil {
            delegate?.didMessageEditDone(self, message: txMessage.text!)
        }
        _ = navigationController?.popViewController(animated: true)
    }
  • EditViewController 소스 파일에 해당 코드 추가하기
  • 수정화면의 텍스트필드를 위한 textMessage 변수 선언과 텍스트필드 값 설정
  • 델리게이트 프로토콜 작성
  • [완료] 버튼을 클릭하면 프로토콜 메소드가 호출되어 텍스트필드 값이 메인화면 컨트롤러에 전달된다.

class ViewController: UIViewController, EditDelegate {
	override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        let editViewController = segue.destination as! EditViewController
        if segue.identifier == "editButton" {
            editViewController.textWayValue = "segue : use button"
        }
        else if segue.identifier == "editBarButton" {
            editViewController.textWayValue = "segue : use Bar Button"
        }
        
        //추가 코드
		editViewController.textMessage = txMessage.text!
        editViewController.delegate = self
    }
    func didMessageEditDone(_ controller: EditViewController, message: String) {
        txMessage.text = message
    }
}
  • ViewController 소스 파일에 해당 코드 추가하기
  • EditViewController 에서 프로토콜 메소드를 호출하면 메시지가 전달되어 메인화면의 텍스트필드에 나타난다.
  • 메인화면의 텍스트필드 값이 뷰 전환되면서 수정화면 컨트롤러에 전달된다.

💻 Step 4. 수정화면에서 메인화면의 전구 제어하기

  • 메인화면에 이미지 뷰 배치하기
  • 수정화면에 '켜기' 레이블과 스위치 배치하기
  • 이미지 뷰와 스위치에 대한 아웃렛 변수 추가하기

class ViewController: UIViewController, EditDelegate {
    
    //추가 코드
    let imgOn = UIImage(named: "lamp_on")
    let imgOff = UIImage(named: "lamp_off")
    var isOn = true

    @IBOutlet var txMessage: UITextField!
    @IBOutlet var imgView: UIImageView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        //추가 코드
        imgView.image = imgOn
    }
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        let editViewController = segue.destination as! EditViewController
        if segue.identifier == "editButton" {
            editViewController.textWayValue = "segue : use button"
        }
        else if segue.identifier == "editBarButton" {
            editViewController.textWayValue = "segue : use Bar Button"
        }
        editViewController.textMessage = txMessage.text!
        editViewController.isOn = isOn
        editViewController.delegate = self
    }
    
    //추가 코드
    func didImageOnOffDone(_ controller: EditViewController, isOn: Bool) {
        if isOn {
            imgView.image = imgOn
            self.isOn = true
        }
        else {
            imgView.image = imgOff
            self.isOn = false
        }
    }
  • 메인화면 컨트롤러 소스 파일에 해당 코드 추가하기
  • 앱 실행 시 첫 화면에서 켜져 있는 전구가 나타난다.
  • EditViewController 에서 프로토콜 메소드 호출 시, 이미지와 변수 값이 변경된다.

protocol EditDelegate {
    func didMessageEditDone(_ controller: EditViewController, message: String)
    
    //추가 코드
    func didImageOnOffDone(_ controller: EditViewController, isOn: Bool)
}

class EditViewController: UIViewController {
    var textWayValue: String = ""
    var textMessage: String = ""
    var delegate: EditDelegate?
    
    //추가 코드
    var isOn = false

    @IBOutlet var txMessage: UITextField!
    @IBOutlet var lblWay: UILabel!
    @IBOutlet var swIsOn: UISwitch!
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        lblWay.text = textWayValue
        txMessage.text = textMessage
        
        //추가 코드
        swIsOn.isOn = isOn
    }
    
    @IBAction func btnDone(_ sender: UIButton) {
        if delegate != nil {
            delegate?.didMessageEditDone(self, message: txMessage.text!)
            
            //추가 코드
            delegate?.didImageOnOffDone(self, isOn: isOn)
        }
        _ = navigationController?.popViewController(animated: true)
    }
    
    //추가 코드
    @IBAction func swImageOnOff(_ sender: UISwitch) {
        if sender.isOn {
            isOn = true
        }
        else {
            isOn = false
        }
    }
  • 수정화면 컨트롤러 소스 파일에 해당 코드 추가하기
  • 스위치 값에 따라 변수값이 변경된다.
  • [완료] 버튼을 클릭하면 프로토콜 메소드가 호출되어 isOn 변수 값이 메인화면 컨트롤러로 전달된다.

💻 Final Step. 전체 소스 코드

  • ViewController.swift
import UIKit

class ViewController: UIViewController, EditDelegate {

    let imgOn = UIImage(named: "lamp_on.png")
    let imgOff = UIImage(named: "lamp_off.png")
    var isOn = true

    @IBOutlet var txMessage: UITextField!
    @IBOutlet var imgView: UIImageView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        imgView.image = imgOn
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        let editViewController = segue.destination as! EditViewController
        if segue.identifier == "editButton" {
            editViewController.textWayValue = "segue : use button"
        }
        else if segue.identifier == "editBarButton" {
            editViewController.textWayValue = "segue : use Bar Button"
        }
        editViewController.textMessage = txMessage.text!
        editViewController.isOn = isOn
        editViewController.delegate = self
    }
    
    func didMessageEditDone(_ controller: EditViewController, message: String) {
        txMessage.text = message
    }
    func didImageOnOffDone(_ controller: EditViewController, isOn: Bool) {
        if isOn {
            imgView.image = imgOn
            self.isOn = true
        }
        else {
            imgView.image = imgOff
            self.isOn = false
        }
    }

}

  • EditViewController.swift
import UIKit

protocol EditDelegate {
    func didMessageEditDone(_ controller: EditViewController, message: String)
    func didImageOnOffDone(_ controller: EditViewController, isOn: Bool)
}

class EditViewController: UIViewController {
    var textWayValue: String = ""
    var textMessage: String = ""
    var delegate: EditDelegate?
    var isOn = false

    @IBOutlet var txMessage: UITextField!
    @IBOutlet var lblWay: UILabel!
    @IBOutlet var swIsOn: UISwitch!
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        lblWay.text = textWayValue
        txMessage.text = textMessage
        swIsOn.isOn = isOn
    }
    
    @IBAction func btnDone(_ sender: UIButton) {
        if delegate != nil {
            delegate?.didMessageEditDone(self, message: txMessage.text!)
            delegate?.didImageOnOffDone(self, isOn: isOn)
        }
        _ = navigationController?.popViewController(animated: true)
    }
    @IBAction func swImageOnOff(_ sender: UISwitch) {
        if sender.isOn {
            isOn = true
        }
        else {
            isOn = false
        }
    }
    
    /*
    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // Get the new view controller using segue.destination.
        // Pass the selected object to the new view controller.
    }
    */

}
profile
언젠간 iOS 개발자가 되겠지

1개의 댓글

comment-user-thumbnail
2023년 10월 20일

코코랄 귀여워요

답글 달기