BOID

[iOS] 데이터 직접 전달하는 방식 (동기방식) -HoonIOS 본문

IOS 시작기

[iOS] 데이터 직접 전달하는 방식 (동기방식) -HoonIOS

HoonIOS 2021. 4. 3. 12:55

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

안녕하세요 저번 포스팅에는 데이터를 주고받는 방법인 동기 방식, 비동기 방식에 대해 알아봤습니다.

https://boidevelop.tistory.com/33

 

[iOS] 다른 뷰컨트롤러와 데이터 주고받기 - HoonIOS

안녕하세요 HoonIOS입니다. :) 이번에는 뷰 컨트롤러들 사이에 값을 주고받는 방식인 직접 전달하는 방식, 간접 전달하는 방식에 대해 포스팅을 해보겠습니다. 뷰 컨트롤러들 사이에 값을 주고받

boidevelop.tistory.com

따라서 이번에는 동기방식으로 데이터를 주고받는 방법, 다음에는 비동기와 세그웨이를 통해 데이터를 주고받는 법에 대해 포스팅을 하겠습니다.

 

* 다시 간단하게 동기 방식에 대해 알아보겠습니다.

- 저장소를 거치지 않고 다음 뷰 컨트롤러로 바로 이동하는 방식으로 화면이 전환되기 전에 이미 값이 전달되므로 값이 소멸될 일이 없습니다.

 

동기 방식을 이용해서 뷰 컨트롤러에 직접 값을 전달하기

- 값을 전달하는 뷰컨을 VC1, 값을 전달받을 뷰컨을 VC2라고 하겠습니다, 큰 형태로 전달하는 방법을 순서대로 설명해보겠습니다.

- 첫 번째로!!!, 동기 방식이므로 VC2에 전달해야 할 값들을 명확하게 선정을 해야 합니다. 따라서, VC2에 전달받을 값을 대입할 수 있도록 VC2에 프로 피티를 미리 정의를 해야 합니다.

- 따라서 정리를 다시 해보면 가장 중요한 점은 전달한 값과 전달받을 값의 프로퍼티 개수와 값의 타입이 일치해야 합니다!!!!

- 여러 개의 데이터를 주고받아야 할 경우 NSMutableDictionary값은 집합 자료형을 사용을 하면 데이터를 주고받을 때 훨씬 편리합니다.

그 이유는 전달할 값의 개수나 타입 관계없이 하나로 모아서 전달할 수 있다.

 

* NSMutableDictionary이란 무엇일까요?
 - 딕셔너리라고도 부릅니다.
 - 키와 값(key, value)으로 구성한것으로 저장순서는 없습니다.
 - 구성 형태
   [Key: Value]
- 값을 수정할수 있는 딕셔너리로 NSDictionary하고 이부분이 다릅니다.

 

두 번째로!!!, 이제는 이동할 VC2의 인스턴스를 VC1으로 가져가야 됩니다. 어렵지 않죠, 저번 화면 전환하기 포스팅에서 했던 방식을 사용하면 됩니다.

- 뷰 컨트롤러의 인스턴스를 직접 생성하는 .instantiateViewController(withidentifier:)메소드를 사용하면 됩니다.

 

* .instantiateViewController(withidentifier:)와 instantiateViewController(identifier:)의 차이는?
- 우선 애플 문서에 있는 정의를 먼저 살펴 보겠습니다.

- identifier은  초기화 코드를 이용해서 지정된 스토리보드의 뷰컨트롤러 인스턴스를 생성합니다.
- withidentifer은 초기화 코드를 이용하여  뷰 컨트롤러 인스턴스와 스토리보드부터의 데이터를 초기화하면 인스턴스를 생성하는 것입니다.

- identifer은 스토리 뷰 컨트롤러 인스턴스를 withidentifier은 스토리보드와 스토리보드의 데이터를 같이 초기화합니다. 

 

- 추후에 세그웨이도 포스팅하겠지만 세그웨이를 이용했다면. destination 속성을 이용하여 인스턴스 참조를 읽어오기만 하면 됩니다.

 

자!!!! 이제 큰 틀을 통해 진행 순서를 이야기했으니 이제 한번 실습으로 만들어 보겠습니다.

1. VC1에 입력 데이터 넣기

- 이름, 알람, 목표 공부시간, 알람 스위치 값을 체크할 알람 ON, 스테퍼에 따라 공부시간을 표시할 ~0분을 레이블로 설정하고 textField, switch, stepper를 정의하고 Done버튼을 누르면 다음 페이지로 전달하도록 하겠습니다.

 

- 해당 각 텍스트 필드랑 스위치, 스테퍼를 VC1에 아울렛 변수로 추가해줍니다.

 

 

- 이제 스위치랑 스테퍼의 값을 표시할 레이블들도 아울렛 변수로 추가해줍니다.

 

 

만약 아울렛 변수나 아울렛 변수를 어떤게 추가했는지 알고싶으면 커넥션 인스펙터를 이용하면 편리합니다 :) 밑에를 보시면 지금까지 설정되있는거 나와있는거 보이시죵?
커넥션 인스펙터

 

- 스위치 컨트롤러의 상태에 따라 알람 상태 레벨이 바뀌는 액션 메소드와 스테퍼에 따른 값이 변화하는 액션메소드를 추가해줍니다.

  • 여기서 주의할 점은 액션 메소드를 추가해 줄 때 Type항목을 UISwitch, UIStepper로 해주는 것입니다. Any타입으로 선언하면 액션메소드를 공용으로 사용할 수 있어 편리하지만 해당 인자 값을 사용할 때 다시 하위 타입으로 캐스팅해주어야 할기 때문에 거추장스러울 수 있습니다.
    ( 그렇지만 나중에 되면 코드로 캐스팅이 편할 수 있는데 이럴 때 하위 캐스팅을 하면 nil값을 받을 수 있는 위험이 있어 guard문을 통해 변수에다가 캐스팅한 값을 넣어주면 됩니다.)

액션메소드 타입 설정

-  개별 타입과 Any 타입은 언제 어떻게 선택할까요?

  • 개별 타입을 선택할 때
  1.  액션 메서드를 호출한 컨트롤의 속성 값이 필요하거나, 제어할 때
  • Any 타입을 선택할 때
  1. 서로 다른 타입의 컨트롤이 동일한 액션메소드를 호출하게끔 하고싶을때 ( 캐스팅을 따로해주고 조건문으로 구문해주면 되겠죠? )
  2. 액션 메소드를 호출한 컨트톨의 정보가 필요 없을 때
  3. 개별 타입을 반드시 사용해야 하는 경우를 제외한 나머지 모든 경우 

- Switch 액션 메소드를 먼저 보면 switch의 상태는 isON으로 확인할 수 있습니다. isON이 true이면 switch의 상태는 켜져 있는 상태이므로 알람 ON이 되고 isOn이 false가 되면 상태가 꺼져있는 것이 됩니다.

- 위 코드를 보면 스위치의 상태에 따라 켜져 있으면 alramCheck의 레이블을 알람 ON, alramCheck의 레이블이 꺼져있으면 레이블을 알람 OFF로 바꿔준다. 여기서 label의 텍스트 값을 바꿔주기 위해서 self. 레이블 아웃렛. text를 통해 텍스트에 접근해 주면 됩니다.

 

- 이제 Stepper의 액션 메소드를 한번 봐보겠습니다. 

스테퍼의 값을 읽어오려면 value 속성을 사용하면 됩니다.

- stepper의 value값은 실수이므로 Int형으로 바꿔주어야 하고 이 값을 text에다가 넣어서 바꿔주면 됩니다.

형태) Int(스테퍼. value)

- 이제 결과를 한번 봐보겠습니다, 스위치에 따라 레이블이 바뀌는지 스테퍼에 따라 레이블이 바뀌는지 확인해봅시다 ㅎㅎㅎㅎㅎㅎㅎ :)

 

 

이제 세팅은 모두 끝났습니다. 이 값들을 다음 화면은 VC2에 전달을 하는 과정을 살펴보겠습니다.

2. VC2에 전달받을 프로퍼티 정의

- 값을 받아오기 위해 화면에서 전달받을 값을 다음 VC2를 표시해주어야 합니다.

- VC2의 스토리 보드 id(identifiy) 도 설정해주고 뷰 컨트롤러도 swift파일과 연결해 줍니다.

- 이제 변경할 레이블을 아울렛변수로 정의해주고 전달되는 값을 대입받을 프로퍼티들을 정의해 줍니다.

  • 오라 왜? 값을 받을 프로퍼티를 정의해주죠? 아울렛 변수에 바로 넣으면 안되나요? 라고 생각을 하셨을수 있습니다.
    정답은 안됩니다....ㅠㅠㅠ
    - 아울렛 변수는 외부에서 값을 직접 대입할 수 없는 변수입니다. 또 아울렛 변수는 외부객체에서 직접 참조를  할수 없도록 제한되어 있어 다른 변수를 생성해주고 값을 받아 레이블로 주입시켜주어야 합니다. 

VC2에서 받을 준비는 끝났습니다. 이제 VC1에서 던질 준비를 하는 작업을 해야겠죠?

3. VC1에 값을 전달받을 뷰 컨트롤러 인스턴스 생성( VC2 인스턴스를 생성 )

- 값을 전달받을 VC2화면의 인스턴스를 생성합니다.

- VC2의 인스턴스는 언제 생성할까요?

  • 너무 일찍 VC2의 인스턴스를 생성하면 메모리 낭비니깐 화면을 전환하기 직전에 VC2의 인스턴스를 생성해주면 됩니다.

- 이 실습에서는 Done버튼을 눌렀을 때 인스턴스를 생성해주는게 제일 좋을거 같습니다.

- 그럼 Done버튼을 눌렀을때 스토리보드 인스턴스를 한번 생성해 보겠습니다.

- 어라? 왜 VC2의 뷰컨인 ViewController2 클래스로 다운 캐스팅을 하는 것일까요?

  • 이유는 단순히 화면을 전환하는 것이라면 상관이 없지만 ViewController2에서 정의한 프로퍼티를 사용하기 때문입니다.
    ( 만약 캐스팅을 하지 않았으면 vc2의 타입은 UIViewController타입의 인스턴스가 생깁니다. )

이제 VC1에서 VC2로 값을 던지고 화면을 전환하겠습니다.

4. VC1의 값을 VC2에 전달하고 화면 전환하기

- 이제 값을  전달하는 부분을 보면 값을 주는 쪽과 값을 받는 쪽의 타입이 맞아야 할 수 있는 것을 볼 수 있습니다. 안 맞으면 에러 뜨니 이거는 정말 중요! 합! 니! 다!

- 특히 텍스트 필드는 입력값을 읽어 들일 때 text속성이 비어있을 경우로 대비해 옵셔널 타입으로 선언되어있어 강제 언래핑(! )을 해주어야 합니다.

- 또 여기서 중요한 것은 바로 present의 위치입니다. 앞 포스팅에서 말한 것처럼 값을 전달을 하고 화면을 전환을 해야 전환 도중 값이 전달되어 값 손실이 일어나는 일이 일어나지 않습니다. 

 

값을 전달받았네요 이제 이 값을 표시해야겠죠?

5. VC2에 전달받은 값을 표시

- 여기서 중요한 부분은 전달받은 값을 화면에 표시하려는 부분인데 적절한 시점을 선택해 주어야 합니다.

- 일반적으로 값을 표시하기에 가장 적절한 시점은 화면이 메모리에 로드되고 난 후 직후입니다. 바로 viewDidLoad() 메소드 부분입니다.

- 이 메소드는 상위 클래스에서 이미 정의된 메소드 이므로 사용을 하려면 재정의를 해주어야 합니다.

* 여기서 주의해야 할점은 3항연산자 입니다.

형태)
    A ? B : C
    - A가 참이면 B 거짓이면 C라는 말입니다.

 -viewDidLoad는 화면이 메모리에 모두 로드되고 난 후 이 메소드가 호출되는데 앱이 화면에 처음 로드될 때 한 번만 호출이 되므로 중복 실행되지는 않습니다.

 

이제 값을 전달하고 화면을 표시하는 것 까지 다 완료를 했습니다. ㅎㅎㅎㅎ 정말 기네요....ㅠㅠㅠ 근데 이렇게 끝나면 이상하지 않을까요? 값을 전달하고 화면을 바꿨는데 값을 바꾸고 싶으면 뒤로 가야 되는데 뒤로 가기 기능을 실행하지 않았네요 이제 VC2에서 화면을 뒤로가는 기능을 구현해 보겠습니다.

6. VC2에서 화면 뒤로가기

- 이번 실습에서는 present를 통해 화면을 전환했으니 당연히 뒤로 갈 때는 dismiss로 화면을 전환해야 합니다 :)

만약 이 부분이 이해가 안 되신다면 화면 전환하기 포스팅을 읽고 오시는 걸 추천드려요 상당히 기본 중의 기본입니다.

- 당연히 dismiss의 위치는 Back 버튼의 아웃렛 액션 메소드 안에다가 구현을 해주면은 되겠습니다.

 

7. 결과

 

결과

 

드디어 길고 긴 뷰 컨트롤러에 직접 값을 전달하기 위한 방법인 동기방식에 대해 알아봤습니다 :)

 

다음에는 이제 내비게이션 컨트롤러에서 값을 전달하는 방식에 대해 포스팅하겠습니다. 이것은 뷰컨 직접 전달과 다르지 않으므로 그렇게 어려우시진 않을 거입니다. ㅎㅎㅎ

긴 글 읽어주셔서 감사합니다 :)

반응형
Comments