Do it! 스위프트로 아이폰 앱 만들기
11장 네비게이션 컨트롤러 이용해 화면 전환하기
- 아이폰 화면 전체를 클릭한 후 메뉴에서
Editor -> Embed in -> Navigation Controller 선택하기- 뷰 컨트롤러의 타이틀 변경하기
- Library 에서 View Controller 를 찾아 메인화면 컨트롤러 오른쪽에 놓기
- Library 에서 Bar Button Item 을 찾아 메인화면 컨트롤러의 네비게이션 바 오른쪽에 놓기
- Bar Button Item 을 우클릭 드래그하여 오른쪽의 뷰 컨트롤러에 갖다 놓고 Action Segue 의 Show 선택하기
- 생성된 세그웨이의 Identifier 를 editBarbutton 으로 수정하기
- 메인화면 컨트롤러에 [수정] 버튼 추가하기
- 수정화면 컨트롤러에 레이블과 [완료] 버튼 추가하기
- [수정] 버튼을 우클릭 드래그하여 수정화면 컨트롤러에 갖다 놓고 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 에게 다른 데이터 값을 전달한다.
- 메인화면과 수정화면에 메시지 전달을 위한 레이블과 텍스트필드 배치하기
- 각 텍스트필드에 대한 아웃렛 변수 추가하기
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 에서 프로토콜 메소드를 호출하면 메시지가 전달되어 메인화면의 텍스트필드에 나타난다.
- 메인화면의 텍스트필드 값이 뷰 전환되면서 수정화면 컨트롤러에 전달된다.
- 메인화면에 이미지 뷰 배치하기
- 수정화면에 '켜기' 레이블과 스위치 배치하기
- 이미지 뷰와 스위치에 대한 아웃렛 변수 추가하기
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 변수 값이 메인화면 컨트롤러로 전달된다.
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
}
}
}
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.
}
*/
}
코코랄 귀여워요