아직은 개린이

[iOS] prepare 메소드란? 본문

Swift + iOS/iOS

[iOS] prepare 메소드란?

jiyeonlab 2019. 11. 22. 17:49

지난번 segue 연결 포스팅에서 performSegue(withIdentifier: sender:) 메소드가 불리기 전에 prepare(for segue: sender:) 메소드가 먼저 호출된다는 부분이 있었다.

이부분에 대해 정확히 알아보고, 주의해야할 점에 대해서도 알아보자!

 


prepare(for segue: sender:) 메소드

새로운 ViewController 클래스를 만들기 위해, File > New File > Cocoa Touch Class 를 생성하게 되면, 아래 첨부한 코드처럼 기본적으로 viewDidLoad() 메소드가 정의되어있고, prepare(for segue: sender:) 메소드가 주석처리 되어있다.

 

ViewController 클래스를 새로 만들면, 기본적으로 적혀있는 코드.

 

주석으로 되어있는 부분을 읽어보면, 

 

 In a storyboard-based application, you will often want to do a little preparation before navigation.

스토리보드 기반의 어플리케이션에서, 당신은 네비게이션 전에 약간의 준비를 하는 것이 좋을 것이다.

 

다른 ViewController로 전환하기 전에 그 ViewController로 데이터들을 보낸다고 생각할 수 있겠지.

 


예제를 통해 알아보자

ViewController의 TextField에 입력한 내용을 prepare 메소드를 이용하여 SecondViewController에 전달하고, Label에 나타내보자.

 


1. ViewController에는 text를 입력받을 TextField와 누르면 SecondViewController로 이동하는 Button을 추가한 후, SecondViewController로 Segue를 연결했다. SecondViewController에는 ViewController로 부터 받은 text 데이터를 보여줄 Label을 추가했다. 또한, ViewController를 Navigation Controller로 Embed 했다.

 

ViewController, SecondViewController 셋팅

 

2. ViewController 코드에 textField를 Outlet으로 연결하고, prepare(for segue: sender:) 메소드에서 segue.destination 객체를 SecondViewController 타입으로 다운캐스팅을 할 수 있을 때, textField에서 입력받은 text를 SecondViewController의 receivedText로 보내준다.

 

 

3. SecondViewController에서는 ViewController로 부터 전달받은 text를 저장해 둘 receivedText 변수를 선언하고, 화면에 보여줄 Label을 Outlet으로 연결한다. 그리고 view가 보여지기 전 호출되는 viewWillAppear(animated:) 메소드에서 receivedText를 label에 넣어준다.

 

 

4. 결과화면

 

 


주의사항

여기서 궁금증이 하나 생긴다!

SecondViewController에 receivedText라는 변수를 따로 선언하지 않고, 아래 코드처럼 바로 textLabel.text에 넣어주는게 더 간단하지 않을까???

 

정답은.... 안된다!!

 

ViewController 에서 "Go to SecondView" 버튼을 누르면, Exception되어버린다!

 


 

왜냐하면!

  • prepare 메소드 내에서 secondViewController 객체의 인스턴스를 가져오긴 했지만, 아직 뷰의 요소들은 메모리에 올라가 있지 않은 상태이기 때문이다!
  • 즉, 인스턴스에 있는 변수인 receivedText는 있지만, 화면에 보여줄 view의 요소에 해당하는 textLabel은 아직 생성이 안된 상태인거지!

 

그래서 디버깅 창에서 "nextViewController가 메모리에 있는지 보여달라!" 라는 디버깅 명령어 (po: print object) 를 적어보면, 해당 객체의 메모리 주소가 찍힌다.

 

 

하지만, "nextViewController.textLabel 이 메모리에 있는지 보여달라!" 라고 하면, nil이 찍히는 것을 볼 수 있다. 

 

 


po nextViewController.receivedText를 찍어봐도 nil이 나오는데, 이건 SecondViewController에서 receivedText를 옵셔널 변수로 선언해줬기 때문이다. 임의의 string을 초기화 값으로 넣어주면, nil이 안찍힘!  -> 보통 외부로부터 데이터를 받을 때는 View와 관련된 프로퍼티에 직접 받지 않고, 외부로 부터 받을 데이터를 저장하는 프로퍼티를 따로 선언하여 할당받는다. 

 


정리

ViewController 간에 데이터를 전달할 때 사용되는 prepare(for segue: sender:) 메소드에 대해서 알아보았다. prepare 메소드를 사용하는 것말고도 ViewController 간의 데이터를 전달하는 방법들이 있는데 이 또한 정리를 해봐야할 것 같다!