본문 바로가기

개발/iOS

[SwiftUI Essentials] Handling User Input - 1

지난 튜토리얼들을 통해 이미 작성된 랜드마크 데이터를 활용하여 랜드마크 List view를 만들었고 조회를 원하는 랜드마크를 선택하였을 때 해당 랜드마크의 세부 정보를 볼 수 있는 화면으로 이동하는 Navigation 기능을 구현하였다. 랜드마크의 세부 정보 화면에서는 이전 화면에서 정보를 받아 MapKit을 통해 위도와 경도 좌표로 랜드마크의 위치를 표시하였고(MapView) 이미지를 보여주고(CircleImage)나 랜드마크의 이름, 세부 정보 등을 보여주는 View를 구현하였다.

 

여태까지 작성한 어플리케이션은 유저의 상호작용이 많이 들어가지는 않는다. 유저는 단순히 리스트를 보다가 원하는 랜드마크를 선택하고 원하는 랜드마크의 세부정보를 보기만 할 뿐이다. 지금부터 시작할 Handling User Input에서는 유저가 좋아하는 장소를 선택하고 좋아하는 장소만 볼 수 있도록 하는, 유저의 상호작용을 높힐 수 있는 기능들을 구현한다.

 

좋아하는 장소 표시

튜토리얼에서는 사용자가 좋아하는 장소를 표시하도록 하는 기능의 구현을 바로 들어가지 않고 데이터에 있는 `isFavorite` 속성을 받아와서 true로 되어 있는 데이터들에 대해서 별 모양을 표시하는 기능을 구현하는 것 부터 시작한다.

 

이 기능이 구현을 위해서는 우선 모델에 해당하는 Landmark.swift를 수정해줘야 한다. isFavorite 속성은 이미 데이터 파일에 저장되어 있다. Landmark 모델을 정의할 때 `Codable`하게 정의해뒀기 때문에 데이터에 같은 이름을 가진 key 값이 존재한다면 해당 값을 읽어올 수 있다. 

 

// Landmark.swift
struct Landmark: Hashable, Codable, Identifiable {
    var id: Int
    var name: String
    var park: String
    var state: String
    var description: String
    var isFavorite: Bool
    
    // ...
   
 }

 

이제 모델에서 좋아하는 장소인지에 대한 정보를 받아올 수 있으니 리스트에서 각 랜드마크에 좋아하는 장소인지 여부를 사용자가 알 수 있도록 해줘야 한다. SwiftUI에서는 if문 내에 view를 포함하도록 작성할 수 있다. isFavorite 속성을 읽어 true일 경우 별 모양 이미지를 띄우도록 한다. 이 때, 별 모양 이미지의 색을 가시성이 좋게 노란색으로 변경해주었다.

 

// LandmarkRow.swift
import SwiftUI

struct LandmarkRow: View {
    var landmark: Landmark
    
    var body: some View {
        HStack {
            landmark.image
                .resizable()
                .frame(width: 50, height: 50)
            Text(landmark.name)
        
            Spacer()
            
            if landmark.isFavorite {
                Image(systemName: "star.fill")
                    .foregroundColor(.yellow)
            }
        }
    }
}

 

좋아하는 장소가 표시가 된다.

 

여기까지 코드를 완성하면 사진과 같이 좋아하는 장소에 대해 별 모양을 표시할 수 있게 된다.

 

리스트에서 좋아하는 장소만 보기

데이터에서 좋아하는 장소인지 여부를 읽어 별 모양을 표시하는 기능을 구현하였다. 다음 섹션에서는 좋아하는 장소만 리스트에서 볼 수 있는 기능을 구현한다. 이 때, `@State` 속성이 사용된다.

LandmarkList.swift 파일에 @State 속성을 가진, 상태 정보를 저장할 변수를 하나 선언한다. 이 상태 정보 변수를 사용하여 원하는 기능을 구현할 것이다.

 

//LandmarkList.swift
import SwiftUI

struct LandmarkList: View {
    @State private var showFavoritesOnly = false
    
    var filteredLandmarks: [Landmark] {
        landmarks.filter { landmark in
            (!showFavoritesOnly || landmark.isFavorite)
        }
    }
    
    var body: some View {
        NavigationView {
            List(filteredLandmarks) { landmark in
                NavigationLink(destination: LandmarkDetail(landmark: landmark)) {
                    LandmarkRow(landmark: landmark)
                }
            }
            .navigationTitle("Landmarks")
        }
    }
}

 

좋아하는 장소인지 아닌지를 보이기 위한 상태 변수 showFavoritesOnly를 선언하였다. 그리고 이 상태 변수를 사용하여 랜드마크들에 대해서 원하는 조건을 만족하는 요소들을 `filter` 메소드를 통해 filteredLandmarks에 저장한다. 현재는 상태 변수를 false로 설정해두었기 때문에 filter 메소드 내의 모든 조건이 true가 되어 모든 랜드마크들이 화면에 표시될 것이다. 좋아하는 장소만 보고 싶다면 상태 변수를 true로 설정하면 된다.

 

좋아하는 이미지만 확인할 수 있다.

 

이렇게 좋아하는 이미지만 따로 확인할 수 있다.

 


 

이번 포스팅에서는 저장된 정보와 하드 코딩을 통해 좋아하는 장소를 화면에 표시하고, 좋아하는 장소만 리스트에서 표시할지에 대한 기능들을 구현하였다. 다음 튜토리얼에서는 이제 사용자가 직접 이 기능들을 앱 내에서 실행할 수 있도록 하는 부분들에 대한 내용을 다루게 될 것이다.

반응형