Switching View and Passing Data(2) - Code
안녕하세요. 오늘은 unwind
를 이용한 데이터 전달에 이어 Delegate
를 활용한 데이터 전달에 대해 보도록 하겠습니다.
이 글을 읽어보시기 전 반드시. Delegate
과 UITableView
에 관한 지식이 있으셔야 합니다. 제가 포스팅한 글도 있으니 참고하시기 바랍니다.
그리고 본 포스팅은 이전 포스팅을 바탕으로 작성하였습니다.
그럼 본격적으로 시작해보도록 하겠습니다.
UI 구성은 위의 UI 세팅 내용을 그대로 사용하였기 때문에 다루지 않도록 하겠습니다.
1. Basic Setting
먼저 ViewController
와 AddViewController
의 요소들을 각각 IBOutlet
으로 연결시켜 줍니다. 물론 AddViewController
의 Save
버튼은 IBAction
으로 연결하는 것을 잊지마세요!
ViewController.swift > ViewController.class
class ViewController: UIViewController, UITableViewDataSource{
@IBOutlet weak var friendListTableView: UITableView!
private var friendList = [[String:String]]()
override func viewDidLoad() {
super.viewDidLoad()
friendListTableView.dataSource = self
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return friendList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath)
-> UITableViewCell {
let cell = tableView.dequeueReusableCell(
withIdentifier:"friendcell",
for: indexPath)
return cell
}
}
- 먼저 친구들의 데이터를 딕셔너리의 배열의 형태로
key-value
형식으로 저장할 것이기 때문에 다음과 같이friendList
를 선언해주었습니다. - 항상
friendListTableView.dataSource = self
작성해주는 것을 잊지마세요.
- 위에서 언급하였듯이
TableView
나 관련 프로토콜에 대한 설명은 이 포스팅에서는 다루지 않도록 하겠습니다.
AddViewController.swift > AddViewController.class
class AddViewController: UIViewController {
@IBOutlet weak var nameTextField: UITextField!
@IBOutlet weak var phoneTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func saveBtnTapped(_ sender: Any) {
}
}
이렇게 기본적인 세팅은 끝났습니다. 이제 본격적으로 코드를 작성해보도록 하겠습니다.
2. Protocol and Delegate
이번 포스팅에서는 Delegate
를 통해 데이터를 전달해줄 것이라고 말씀드렸습니다. 제가 Delegate
포스팅에서도 언급했듯이 Delegate
는 객체간의 상호작용이고 이러한 상호작용 중 하나인 데이터 전달해볼 것입니다.
Delegate
를 사용할 때는 다음의 세가지가 필요합니다.
- Protocol - 일의 목록
- Delegate - 일을 해주는 객체
- Master - 일을 위임하는 객체
즉 이번 예제에서는 AddViewController
가 일을 위임하는 객체가 되는 것이고, ViewController
가 일을 하는 객체가 되는 것입니다.
그러면 이제 일의 목록, 즉 Protocol
을 만들어보도록 하겠습니다.
protocol SaveDataDelegate:class {
func saveData(data saveData:[[String:String]])
}
프로토콜을 정의해주었으면 일을 위임하는 객체(AddViewControleller
)에서 일을 대신할 객체를 참조할 변수를 선언합니다.
그리고 AddViewController
에서 Save
버튼을 누르면 현재 친구를 추가하는 화면은 내려가고 데이터가 저장되어야 하기 때문에 다음과 같이 코드를 작성합니다. 그리하여 완성된 AddViewController
는 다음과 같습니다.
AddViewController.swift > AddViewController.class
import UIKit
protocol SaveDataDelegate:class{
func saveData(data saveData:[String:String])
}
class AddViewController: UIViewController {
weak var delegate:SaveDataDelegate?
@IBOutlet weak var nameTextField: UITextField!
@IBOutlet weak var phoneTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func saveBtnTapped(_ sender: Any) {
var data = [String:String]()
data["name"] = nameTextField.text!
data["phone"] = phoneTextField.text!
delegate?.saveData(data: data)
self.navigationController?.popViewController(animated: true)
}
}
이렇게 하면 AddViewController
에서의 작업은 끝이 납니다.
그럼 이제 ViewController
, 즉 실질적으로 데이터를 저장하는 곳에서 함수를 작성해보도록 하겠습니다.
ViewController.swift > ViewController.class
func saveData(data saveData: [String : String]) {
friendList.append(saveData)
friendListTableView.reloadData()
}
간단하죠? 하지만 여기서 문제가 있습니다. 바로 어떻게 AddViewController
와 ViewController
을 "고용" 관계를 설정하냐 입니다. TableView
는 IBOulet
으로 참조 변수를 생성하여 연결시켰지만 AddViewController
는 어떻게 연결시켜야 할까요?
바로 prepare(segue:sender:)
함수를 이용하는 것입니다. 우리가 스토리보드에서 지정한 Segue
는 Add
버튼을 눌렀을 때 ViewController
에서 AddViewController
로 넘어가는 Segue
였습니다. Segue
객체에는 기본적으로 출발지(source
)와 목적지(destination
)이 프로퍼티로 존재합니다. 저는 그것을 활용할 것입니다.
ViewController.swift > ViewController.class
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destination = segue.destination as! AddViewController
destination.delegate = self
}
prepare(segue:sender:)
함수는 Segue
가 발동될 때 (이 예제에서는 Add
버튼이 눌렸을 때) 자동으로 호출되는 함수이고 Segue
에는 source
와 destination
프로퍼티가 존재함으로 다음과 같이 prepare(segue:sender:)
함수안에서 destination.delegate = self
를 해주었습니다.
그리고 마지막으로 Cell
에 데이터를 뿌려주는 코드를 작성하도록 하겠습니다. 먼저 스토리보드로 들어가셔서 TableViewCell
을 선택하시고 셀의 스타일을 Subtitle
로 지정해주세요. 그리고 이제 다음과 같이 작성해주세요.
ViewController.swift > ViewController.class
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath)
-> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "friendcell", for: indexPath)
cell.textLabel?.text = friendList[indexPath.row]["name"]!
cell.detailTextLabel?.text = friendList[indexPath.row]["phone"]
return cell
}
마무리
이렇게 오늘은 Delegate
를 활용한 데이터 전달을 알아보았습니다. 이렇게 Delegate
를 공부하실 때 이것이 정확히 언제 사용되고 내부는 어떻게 돌아가는거지 라고 생각했던 분들은 많은 도움이 됬을 것이라고 생각합니다. 실제로 저도 이해하는데 상당히 많은 도움이 됬구요! 그럼 다음 포스팅에서 뵙겠습니다. 감사합니다!
Source : github
참고자료