BOID

[iOS] 이전 화면으로 값을 전달하기 본문

IOS 시작기

[iOS] 이전 화면으로 값을 전달하기

HoonIOS 2021. 4. 5. 16:53
728x90

안녕하세요 HoonIOS입니다. :)

 

지금까지는 VC1 -> VC2로 값 전달 밑 화면전환에 대해 포스팅을 했는데요. 이번에는 반대로 거꾸로 VC2에서 값을 입력하면 이 값들을 VC1으로 전달하겠습니다.

 

VC1 -> VC2 와 VC2 -> VC1의 다른점

* 첫번째

  • VC2에 입력을 한다는것은 VC1화면이 만들어져 있고, 인스턴스 역시 만들어져 있다는것을 전제로합니다. 따라서 인스턴스를 새로 만드는게 아니라 현재 존재하는 뷰컨트롤러에서 참조값을 가져와야합니다.
  • 여기서 중요한점은 화면 전환 방식에 따라 사용하는게 달라지는데 프레젠테이션 방식이라면 self.presentingViewController를 사용하여 읽어오고 내비게이션 컨트롤러 방식이라면 self.navigationController?.viewControllers 배열 속성을 통해 VC1의 참조값을 읽어올수 있습니다.

* 두번째

  • VC1 -> VC2로 값을 이동 화면을 전환하는 메소드를 사용했지만 VC2 -> VC1로 이동할때는 화면 복귀메소드를 사용해야 합니다. 그 이유는 새로운 화면을 나타내는게 아니라 원래 있던 화면을 걷어내야 되기 때문입니다.
  • 이 경우에도 프레젠테이션은 .dismiss(_:animated:), 내비게이션은 popViewController(_:animated:)와 같이 경우에 따라 복귀 메소드도 달라집니다.

* 세번째

  • 값을 화면에 표시하는 시점이 달라집니다. 화면을 전환할때는 viewDidLoad( ) 메소드 내에 호출했지만, 이제는 화면이 새롭게 표현될때마다 호출되는 viewWillAppear(_:)메소드가 호출됩니다.
    ( 여기서 중요한게 있는데 실습때 알려드릴께요! 이것때문에 고민좀 했습니다...ㅠ )
 º 참조
 - V2 -> V1으로 전달하는 값은 대체적으로 반영구적으로 표현해야하는경우가 많습니다.

 - 예를들어 a, b, c 순서의 뷰컨트롤러가 있다고 합시다. c -> b로 갈때는 값을 가져가고 b -> a로 간다음 다시 a -> b로 간다고 할때 c -> b로 전달 받았던 값이 사라지기 때문입니다.
( 그 이유는 b -> a로 갈때 b의 인스턴스의 메모리가 해제되면서 전달받은 값도 모두 사라지기 때문이죠 또르르...ㅠ )

* 그렇다고 무조건 저장소를 만들라는 말이 아니고 앱의 기능적 성격에 따라 고려해 두는것이 좋습니다!

값을 이전화면으로 전달하기(예시)

- 제일 먼저 값을 받을 VC1을 구성해 보겠습니다.

- VC1의 객체들( ** 표시)을 아울렛변수들을 정의해줍니다.

- 이제 값을 전달받기 위한 프로퍼티를 .swift 파일에 작성을 해줍니다.

* 아무것도 안받은 값들이 올수 있으니 옵셔널로 선언을 해줍니다.

 

 - 값을 받을 준비를 다했으니 이제 화면을 표시를 하려고 합니다. 아까 말씀드린것처럼 VC1은 이미 만들어져 있는 인스턴스이므로 viewDidLoad가 아닌 viewWillAppear로 호출해줍니다. viewDidLoad는 생명주기에서 한번만 호출되기 때문에 또 호출할수는 없습니다.

 * viewWillAppear이란?
 - 메소드는 뷰컨트롤러의 뷰가 화면에 표시될때마다 실행되는 메소드입니다. 다른화면으로 기존화면을 가렸다가 다시 표시할때 이메소드를 호출합니다.
(※ 주의해야할것은 present메소드일때 화면을 .fullscreen으로 해야 호출이 됩니다. 만약 .sheet일때는 호출이 되지 않습니다. ※)
 - 이 메소드도 viewDidLoad처럼 상위클래스의 정의가 되어있으므로 재정의(override)해야 합니다.

- viewWillAppear 메소드에 전달 받은 값들을 구현해보겠습니다.

 

* if let은 옵셔널 바인딩문으로 전달 받은 값들이 옵셔널로 되어있으므로 옵셔널을 해체해주기 위한 코드입니다. 만약 값이 누락되면 아무것도 아무것도 변경되지 않으므로 주의해서 코딩을 해야합니다.

 

- 이제 Redone이라는 버튼을 만들어 줍니다. 이버튼은 VC1 -> VC2로 이동할 버튼으로 present Modally세그웨이 타입으로 세그웨이를 생성해줍니다.

- 그리고 스크린 타입을 .sheet가 아닌 .fullscreen으로 해줘야 viewWillAppear이 호출되므로 이것도 주의해야합니다.

 

 

- 이동할 VC2의 입력 항목과 값을 표기할 레이블, 스위치, 스테퍼, 버튼을 아울렛 변수, 메소드로 지정해줍니다.

 

 

- 값을 전달할 Done버튼의 액션 메소드를 설정해줍니다.

 * preVC 변수는 전달해줄 대상의 뷰컨트롤러(VC1)의 인스턴스를 가져오기 위해 self.presentingViewController 속성을 사용했습니다. 이것은 VC1 -> VC2로 프레젠테이션 할때 사용했던 속성으로 현재의 뷰컨트롤러를 화면에 표시해주고 있는 VC1을 가리키는 의미로 되돌아가야할 화면이기도 합니다.
 * 결과적으로 self.presentingViewController을 통해 VC1 인스턴스를 생성해주고 이 인스턴스에 값을 전달하고 복귀하면 전달과정은 모두 마무리가 됩니다.

 * .presentingViewController란?

공식문서

-  뷰컨트롤러가 제공한 뷰컨트롤러로 present(_:animated:) 메소드를 사용하여 표시해주고 있는 뷰컨트롤러를 의미합니다.

* 그렇지만 여기서 또 문제가 있습니다. 단순히 화면을 뒤로가기위해서는 guard let vc = preVC else { return }을 해서 UIViewController타입으로 리턴을 하면 viewController 클래스에 정의했던 프로퍼티, 메소드들을 사용할수 없습니다.

  • 그 이유는 UIViewController클래스는 viewController클래스의 부모 클래스이므로 자식클래스에서 무엇이 있는지 알수가 없기 때문입니다.

* 따라서 이를 해결하기 위해서 viewController 클래스로 다운캐스팅을 하면은 해결을 할수 있습니다, 단 그냥 as로 캐스팅을 하기보다는 다운캐스팅은 nil을 반환할 가능성도 있으므로 guard문을 통해 안전하게 빼내는게 좋습니다.

 

  • 모두 완료했습니다. 이제 VC2 에서 VC1으로 값이 전달되는지 한번 확인해보겠습니다 :)

 

이제 동기방식으로 직접 전달하는 방식은 모두 했습니다. 이제는 다음포스팅에는 저장소를 이용하여 전달하는 비동기 방식에 대해 알아보겠습니다 :)

반응형
Comments