[SwiftUI] Row에 Favorite 마크 추가하기

원문: 튜토리얼 페이지

Handling User Input

요번에는 랜드마크 목록에 즐겨찾기 마크를 추가하고, 상세 화면에서 즐겨찾기를 추가할 수 있도록 수정해본다. switch를 사용해 즐겨찾기 목록 필터링도 가능하도록 구현한다.

Mark the User’s Favorite Landmarks

Landmark에 즐겨찾기 여부 확인 프로퍼티 추가

Landmark 구조체에 isFavorite 프로퍼티를 추가하고 LanmarkRow에 별 모양이 노출되도록 이미지를 추가한다. (isFavorite가 true면 채워진 별이 노출되어야 한다.)

Landmark는 Codable 하기 때문에 json 파일의 키값과 프로퍼티 명이 동일해야 한다. 현재 json 파일에 isFavorite으로 키 값이 들어있으므로 프로퍼티 명도 동일하게 해주었다.

image

시스템에서 제공하는 star.fill을 사용하면 색이 검정색이다. (images are vector based) 따라서 색을 변경하려면 .foregroundColor(.yellow) 속성을 추가해준다.

Filter the List View

즐겨찾기를 추가한다면 즐겨찾기 목록만을 필터링해서 보여줄수도 있으면 좋지 않을까? 요번 섹션에서는 랜드마크 list 뷰를 즐겨찾기 된 랜드마크만 보여주도록 필터링 처리를 해본다.

row에 별을 추가하고 LandmarkList를 확인해보니 json에 들어있는 대로 즐겨찾기가 true인 row들에는 별이 노출된다.

isFavorite 값이 true인 list만 필터링 하기 위해 LandmarkList에 showFavoritesOnly 프로퍼티를 추가한다.

프로퍼티 추가 시 ` @State private var showFavoritesOnly = false` 이렇게 private을 사용하게 된다. 뷰를 어떤 식으로 노출할지를 판단하는 프로퍼티이므로 외부에서 접근하지 못하도록 private 처리를 한다.

필터링된 랜드마크를 보여줄 수 있도록 filteredLandmarks 프로퍼티를 선언한다. (computed property)

var filteredLandmarks: [Landmark] {
        landmarks.filter { landmark in
            (!showFavoritesOnly || landmark.isFavorite)
        }
    }

body에서 list를 구성할 때 사용하던 landmark 대신 filteredLandmarks를 사용하도록 하고 showFavoritesOnly를 true로 변경한 뒤 화면을 확인해보자.

favorite 표시가 되어있던 랜드마크만 노출이 된다.

Add a Control to Toggle the State

하지만 위에 코드처럼 코드로 필터링을 걸어버리면 원래 보였던 전체 목록으로 돌아갈 방법이 없다. 그래서 이번에는 스위치를 사용해서 전체 목록과 즐겨찾기 목록을 둘다 볼 수 있도록 수정한다.

List 내부에 ForEach 추가

As Is To Be
image image

원래는 List에서 바로 fliteresLandmarks에 접근했다면 이번에는 List 내부에서 ForEach를 통해 filteredLandmarks에 접근한다.

static, dynamic 뷰들을 combine 하거나 두개 이상의 서로 다른 dynamic 뷰들을 combine 할 때는 위와 같이 ForEach를 통해 데이터를 전달해야한다.

토글 추가

ForEach 구문 위에 Toggle을 추가한다. On인 상태는 showFavotiresOnly를 가지고 판단한다. (State 프로퍼티에 접근할 때는 $를 사용..!)

image

showFavoritesOnly 프로퍼티를 false로 바꾼 뒤 실행해보면 잘 동작한다.

Aug-19-2022 17-34-35

마무리

SwiftUI의 세계는 너무 신기하다… List도 뚝딱 만들어지고 toggle도 뚝딱이고.. on/off를 하면 바인딩된 값에 따라 자동으로 화면 업데이트 되는것도 너무 신기해..

Leave a comment