→ ViewController에 의한 값 전달
ViewController TextView에 작성한 text를 다음 버튼을 눌렀을 때 SecondViewController로 전달하여 SecondViewController의 TextView에 띄우기
class SecondViewController: UIViewController {
var textSpace: String = ""
@IBOutlet weak var secondTextView: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
secondTextView.text = textSpace
}
}
@IBAction func buttonClicked(_ sender: UIButton) {
guard let vc = self.storyboard.instantiateViewController(withIdentifier: "SecondViewController") as? SecondViewController else {return}
vc.textSpace = firstTextView.text
self.present(vc, animated: true, completion: nil)
}
→ 클로저를 이용한 값 전달
역으로 값을 전달하는 방식 → 메서드(클로저 구문을 만듦)
→ SecondViewController에서는 클로저 구문을 작성만 함(이거 실행해줘) → 자세한 실행 사항은 FirstViewController에서 작성하면 됨!!
// SecondViewController내에서 클로저 변수 선언
var buttonActionHandler: (() -> ())?
// 실행이 안되는 경우를 대비하여 초기화 구문을 작성하지 않아도 되도록 옵셔널로 선언해줌
@IBAction func buttonClicked(_ sender: UIButton) {
buttonActionHandler()
self.dismiss(animated: true, completion: nil)
}
// firstViewController
@IBAction func buttonClicked(_ sender: UIButton) {
guard let vc = self.storyboard.instantiateViewController(withIdentifier: "SecondViewController") as? SecondViewController else {return}
vc.buttonActionHandler = {
self.firstTextView.text = vc.textView.text
}
vc.textSpace = firstTextView.text
self.present(vc, animated: true, completion: nil)
}
해당 클로저가 어느 시점에서 실행되는지 디버그 창을 통해 확인해보기
// firstViewController
@IBAction func buttonClicked(_ sender: UIButton) {
guard let vc = self.storyboard.instantiateViewController(withIdentifier: "SecondViewController") as? SecondViewController else {return}
vc.buttonActionHandler = {
print("buttonActionHandler")
self.firstTextView.text = vc.textView.text
}
vc.textSpace = firstTextView.text
self.present(vc, animated: true, completion: nil)
}
→ SecondViewController에서 화면 닫는 버튼 누르는 경우 핸들러가 실행되고 이때 print 되는 것을 확인할 수 있음!
vc.buttonActionHandler = { [weak self ] // 이걸 캡쳐..리스트..?라고 하나봐...이건 나중에 알려준다고 함 (순환참조)
print("buttonActionHandler")
self.firstTextView.text = vc.textView.text
}
→ dismiss의 completion 활용 + presentingViewController 사용
// SecondViewController
@IBAction func buttonClicked(_ sender: UIButton) {
buttonActionHandler()
self.dismiss(animated: true) { // completion 타입: (() -> Void)?
guard let vc = self.storyboard.instantiateViewController(withIdentifier: "PopUpViewController") as? PopUpViewController else {return}
self.presentVC.present(vc, animated: true, completion: nil)
}
}
→ popUpView가 한 번 뜨고 닫고 다시 띄우려고 하면 view hierachy 어쩌구 하면서 다시 popupView가 안뜸 ㅜㅜ
이유는 !! 여기서 self = SecondViewController 임
self.dismiss 면 이미 self 즉 SeondViewController는 사라졌음 근데 여기서 self.present하려고 하면 이미 SecondViewController는 사라진 상태이기 때문에 오류가 뜰 수 밖에 없음.
→ 화면 전환할때 property를 두 가지를 더 제공해줌 사용할 수 있도록
→ 현재 SecondViewController가 사라졌기 때문에 mainViewController에게 present 해달라고 요청해야하는 상황임(presentingViewController)
// SecondViewController
@IBAction func buttonClicked(_ sender: UIButton) {
buttonActionHandler()
guard let presentVC = self.presentingViewController else {return} // 나를 띄워준 뷰컨트롤러가 누군지 이 변수에 담아둘게 ...
self.dismiss(animated: true) { // completion 타입: (() -> Void)?
guard let vc = self.storyboard.instantiateViewController(withIdentifier: "PopUpViewController") as? PopUpViewController else {return}
presentVC.present(vc, animated: true, completion: nil)
}
}
// firstViewController
// 버튼 눌렀을 때 신호 + 데이터 보내기~
@IBAction func notificationButtonClicked(_ sender: UIButton) {
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "firstNotification"), object: nil, userInfo: ["myText":secondTextView.text!, "value":123])
self.dismiss(animated: true, completion: nil)
}
@objc func firstNotification(notification: NSNotification) {
print("Notification!1")
if let text = notification.userInfo?["myText"] as? String {
firstTextView.text = text
}
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: "firstNotification"), object: nil)
}
deinit {
NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: "firstNotification"), object: nil)
}
// SeondViewController에 protocol 선언
protocol PassDataDelegate {
func sendTextData(text: String)
}
// secondTextView에 작성된 Text를 역으로 넘겨주기!!
var delegate: PassDataDelegate?
@IBAction func protocolButtonClicked(_ sender: UIButton) {
if let text = secondTextView.text {
delegate?.sendTextData(text: text)
}
dismiss(animated: true, completion: nil)
}
class ViewController: UIViewController, PassDataDelegate
func sendTextData(text: String) {
firstTextView.text = text
}
@IBAction func protocolButtonClicked(_ sender: UIButton) {
guard let vc = self.storyboard?.instantiateViewController(withIdentifier: "SecondViewController") as? SecondViewController else {return}
vc.delegate = self
self.present(vc, animated: true, completion: nil)
}