brunch

You can make anything
by writing

C.S.Lewis

by 윤민섭 Nov 09. 2020

태양계 행성 앱 3

조금 더 재밌는 앱 만들기

지난 글에서 '행성 이미지가 있고 이미지를 누르면 행성에 대한 정보를 알 수 있다.' 기능 구현이 완료됐습니다.


하지만 한 가지 아쉬운 점이 있습니다. 정보가 나왔을 때 화면을 터치하면 정보를 숨기고 싶습니다.

가장 쉬운 방법인 정보 뷰에 터치 인식기를 추가해보겠습니다.


이미지 뷰에 추가했던 방법과 동일하기에 과정은 생략하겠습니다.



터치 인식기가 추가됐다면, 이제 ViewController와 연결하겠습니다. 연결 후 동작은 어떻게 해야 할까요?

정보를 나타내는 뷰가 터치되면 뷰의 alpha 값을 다시 0으로 설정하면 됩니다.



이제 앱을 실행한 후 화면을 터치하면 정보를 나타내는 뷰가 보이고, 한 번 더 터치하면 사라지게 됩니다.


2. 옆으로 넘기면서 행성을 탐색할 수 있다.


이제 두 번째 기능을 구현해야 합니다.


행성을 탐색할 수 있단 것은 행성에 대한 정보들을 갖고 있어야 할 것 같습니다. 행성에 대한 정보를 갖고 있는 방법은 다양합니다. 우선 가장 쉬운 방법으로 SolorSystem.swift 파일을 만들어 보겠습니다.

파일 만드는 방법은 간단합니다. 

상단 바에서 File - New - File으로 만들 수 있으며 command + N 동작으로 가능합니다.



이 파일에 행성에 대한 정보를 기록할 것인데요. 지난 글에서 여러 가지 정보를 담고 있었던 배열에 대해 알아본 적이 있습니다. 이번엔 배열에 행성 이름을 담아두고 행성 정보는 Dictionary(딕셔너리)를 사용하겠습니다.


Dictionary(딕셔너리)는 의미 그대로 사전의 기능을 하는 타입입니다. 영한사전을 생각해보겠습니다. 어떻게 구성되어있나요? "단어" : "뜻" 이렇게 되어있는 것을 확인할 수 있습니다. 같은 뜻을 가진 단어는 있을 수 있지만 같은 단어는 없습니다.


https://blog.aladin.co.kr/common/popup/printpopup/print_review.aspx?paperid=7103922


Swift의 Dictionary도 영한사전처럼 구성되어있습니다. 바로 "키(Key)": "값(Value)"으로 말이죠. 그리고 키 값은 유일합니다. 여기서 Key로 사용할 타입은 AnyHashable 타입만 가능합니다. AnyHashable.. 지금 몰라도 됩니다. String, Int 등으로 사용할 수 있다고 일단 생각하시면 편합니다.


그렇다면 우리는 "행성 이름": "행성 설명"으로 Dictionary(딕셔너리)를 만들 수 있지 않을까요?


행성 이름을 담고 있는 배열을 만들고 행성 정보 Dictionary를 만들겠습니다.



배열과 마찬가지로 값을 구분할 땐 쉼표(,)를 사용합니다. 행성 이름과 행성 정보 Dictionary를 담고 있는 파일은 하단에 첨부했습니다. 


여기서 한 가지 알아야 할 것이 있습니다.  


첫 앱에서 배열을 사용했을 땐 ViewController 내부에 있었습니다. 이렇게 특정 클래스 안에 있는 값은 외부에서 바로 사용할 수 없습니다. 클래스를 생성한 후 값을 사용할 수 있습니다.


 

planetNames, planetInformations는 어디에도 속하지 않습니다. 즉, 이 값들은 어떤 곳에서든(전역적으로) 사용이 가능합니다. 


이제 행성 정보를 다룰 수 있는 준비를 마쳤습니다.


본격적으로 '옆으로 넘기면서 행성을 탐색할 수 있다.' 기능을 구현해보겠습니다.


화면을 옆으로 넘기면 특정 기능이 동작해야겠죠. 옆으로 넘기는 동작을 Swipe 제스처라고 합니다.

이전에는 탭 인식기를 추가했다면, 이번엔 스와이프 인식기를 추가해보겠습니다.



Swipe 인식기는 가장 최상위에 있는 View에 추가하겠습니다. 먼저 Swipe Gesture Recognizer를 좌측 Tap Gesture Recognizer 아래로 드래그합니다. 

Swipe Gesture Recognizer가 추가됐다면 클릭 후 오른쪽 영역에서 New Referencing Outlet Collection을 최상위 뷰로 드래그합니다.



이제 최상위 뷰에서 Swipe Gesture를 인식할 수 있습니다. Swipe Gesture 인식기는 4가지 방향 중 하나를 인식할 수 있습니다. 기본값은 왼쪽 - 오른쪽 방향입니다. 다음 행성으로 간다는 의미는 오른쪽에서 왼쪽으로 손가락을 움직이는 것이 자연스러울 것 같습니다.

이런 경우 Swipe Gesture 인식기의 방향을 왼쪽으로 변경해야 합니다.


Swipe Gesture Recognizer를 클릭 후 오른쪽 영역에서 Attribute Inspector(5번째 버튼)을 클릭한 후 Swipe 영역에서 Right를 Left로 변경합니다.


이제 탭 인식기와 마찬가지로 ViewController에 연결하고 함수의 이름은 간단하게 leftSwipeGesture로 하겠습니다.



앱을 실행한 후 오른쪽에서 왼쪽으로 화면을 쓸면 leftSwipeGesture가 동작하는 것을 확인할 수 있습니다.


 '옆으로 넘기면서 행성을 탐색할 수 있다.'


그렇다면 이제 행성을 탐색할 준비가 끝났습니다. 행성 이름과 행성 정보를 설정해주기 위해선 행성 이름과 행성 정보 Label을 참조할 수 있어야 합니다.


informationView와 마찬가지로 ViewController에 연결합니다.



우선 첫 번째 행성인 수성에 대한 정보를 설정해야 합니다. 물론, 지금은 Storyboard에 직접적으로 정보를 넣어줬지만요.

첫 번째 행성 이름은 planetNames 배열에서, 정보는 planetInformations 딕셔너리에서 가져올 수 있습니다.

설정하는 위치는 viewDidLoad 함수 내부가 적당할 것 같습니다.



딕셔너리에서 값을 가져올 땐 배열처럼 대괄호를 사용하지만 배열과 다르게 Key값을 사용해서 가져와야 합니다. 여기서 Key는 행성 이름이었습니다. 


한 가지 더 추가해야 할 것 같습니다. 바로 행성의 이미지입니다. 행성 이미지 역시 SolarSystem.swift 파일 안에 딕셔너리로 만들어보겠습니다.



이미지는 UIImage라는 타입을 사용하며 Image Literal기능을 사용해 이미지를 추가합니다.



다시 SolarSystemViewController로 이동하여 행성 이미지 뷰를 연결하고 Label과 마찬가지로 이미지를 설정합니다. 



앱을 실행해보겠습니다.



행성 이름과 정보, 이미지가 잘 나오는 것을 확인할 수 있습니다.


이제 leftSwipeGesture 함수를 변경해보겠습니다.


첫 앱과 마찬가지로 index를 사용해야 행성을 탐색할 수 있을 것 같습니다. 이렇게 index를 사용해서 배열에 접근할 땐 항상 범위를 넘어가지 않도록 조심해야겠죠.

태양계 행성은 총 8개이기 때문에 8이란 숫자를 활용할 수 있습니다.



만약 태양계에 행성이 추가됐다고 생각해보겠습니다.

planetNames에 추가된 행성을 입력하고 행성의 개수를 다루는 함수에서도 8에서 9로 변경해줘야 합니다.

그렇게 하지 않는다면 인덱스 에러가 발생하기 때문이죠.


이 앱에선 행성의 개수를 다루는 함수가 하나밖에 없지만 만약 여러 곳에서 사용한다고 생각해보겠습니다.

놓치는 부분이 생길 수 있겠죠?

그렇기 때문에 이렇게 숫자를 활용하지 않고 배열을 사용해 조금 안전하게 값을 다룰 수 있습니다.


바로 배열의 count 값을 사용하는 것입니다. 배열의 count는 배열 안에 몇 개의 값이 있는지 반환합니다.

즉, 여기서 count를 사용하면 8을 반환하겠죠.



여기서 궁금한 점이 생깁니다. 무언가 계산을 해서 값을 반환할 수 있는 것은 함수였습니다. 함수를 사용할 땐 뒤에 소괄호()를 붙입니다. 하지만 count는 무언가 계산을 해서 값을 반환했는데 소괄호가 없습니다.

어떻게 이게 가능할까요?


바로 배열 속 count는 Swift 문법 중 Computed Property(계산 프로퍼티) 이기 때문입니다.

우선, 프로퍼티는 값이라고 생각하면 좋습니다. 기본적으로 우리가 사용했던 변수나 상수는 Stored Property(저장 프로퍼티)로 생각하면 됩니다. 그렇다면 Computed Property는 무엇일까요?


특정 로직을 수행해서 값을 반환하는 값이라고 생각하면 좋습니다. 예를 들어 배열 원소의 개수를 반환하는 count를 직접 구현한다고 생각해보겠습니다.



Computed Property의 모양은 이렇습니다.


var 프로퍼티이름: 타입 { 

      ...

     return 결과

}


intArray를 처음부터 끝까지 순회하면서 count에 1씩 더하는 것을 확인할 수 있습니다. 애플이 내부적으로 구현한 방식과는 다를 수 있지만 이렇게 Computed Property를 사용하면 함수와 비슷하게 값을 계산하고 반환할 수 있습니다.


옆으로 넘기면서 행성을 탐색할 수 있다. 기능도 마무리되었습니다.

왼쪽에서 오른쪽으로 스와이프 했을 때 이전 행성으로 돌아오게 직접 구현해보는 것도 좋겠습니다.


다음 글에서 남은 기능을 구현해보겠습니다.

고맙습니다.




행성 정보



브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari