[SwiftUI] 10. State and Data flow: 값에 바인딩 되는 커스텀 입력 컨트롤 생성

Sean·2023년 5월 4일
0

SwiftUI_튜토리얼

목록 보기
10/11

참고 자료: SwiftUI 튜토리얼 공식문서

이제 막 SwiftUI를 배워보는 한 사람으로서, 코드 작성하고 내가 이해 한 대로 작성할것이다.

이 글의 내용은 위에 있는 참고자료의 공식문서를 번역하여 조금 더 내가 느끼기에 자연스럽게 만들어서 작성하는것이다.

누군가에게 알려주기보다 자신이 정리를 하면서 다시 문서를 보고 어버버거리지 않게 다시 참고하기 위함이기에 해당 문서를 읽는 사람은 swift에 대해서 어느 정도 안다는 가정하에 글을 작성할것이다

시작

값에 바인딩되는 커스텀 컨트롤을 사용해 앱에 고유한 상호 작용을 제공한다.
SwiftUI는 Slider, TextField 및 다른 값에 바인딩되어 상호 작용시 값을 변경할 수 있는 입력 컨트롤을 제공한다.
하지만 모든 앱이 다 같지 않기에 앱에 고유한 동작을 제공하는 커스텀 컨트롤이 필요할 수 있다.

SwiftUI는 앱에 커스텀 컨트롤을 만들기 위해 필요한 빌딩 블록을 제공한다.
이 튜토리얼에서는 이러한 컨트롤 중 하나인 등급 컨트롤의 예시를 알아본다.

분석

1. 커스텀 컨트롤 디자인

StarRating.swift

import SwiftUI

struct StarRating: View {
    @Binding var rating: Int
    private let maxRating = 5

    var body: some View {
        HStack {
            ForEach(1..<maxRating + 1, id: \.self) { value in
                Image(systemName: "star")
                    .symbolVariant(value <= rating ? .fill : .none)
                    .foregroundColor(.accentColor)
                    .onTapGesture {
                        if value != rating {
                            rating = value
                        } else {
                            rating = 0
                        }
                    }
            }
        }
    }
}

커스텀 컨트롤을 구현하기 전에 해당 컨트롤이 필요로 하는 데이터나 데이터 처리 방법, 시각화 방법에 대해서 고민해야 한다.

구조체는 레시피의 등급을 저장하기 위해 바인딩 변수를 정의한다.(@Binding var xxx)
바인딩 변수로 정의됨에 따라 다른 view가 값의 생성을 담당해도 값을 읽고 쓸 수 있다.

forEach는 hashable 타입의 id 매개변수를 사용해 데이터를 식별한다. 매개변수의 값은 identity key path로 각 정수에 대한 Int 인스턴스를 지정한다.
Int 가 hashable 하므로 이 키 경로를 사용하면 foreach 초기화 메서드의 요구사항을 충족시킬 수 있다.

2. 컨트롤을 상호작용 가능하게 만들기

Method: onTapGesture()

StarRating.swift

import SwiftUI

struct StarRating: View {
    @Binding var rating: Int
    private let maxRating = 5

    var body: some View {
        HStack {
            ForEach(1..<maxRating + 1, id: \.self) { value in
                Image(systemName: "star")
                    .symbolVariant(value <= rating ? .fill : .none)
                    .foregroundColor(.accentColor)
                    .onTapGesture {
                        if value != rating {
                            rating = value
                        } else {
                            rating = 0
                        }
                    }
            }
        }
    }
} 

상호 작용을 하는 컨트롤로 만들기 위해서는 onTapGesture 메서드를 사용한다.
해당 메서드는 사용자가 인스턴스를 탭시 클로저에 정의된 작업을 수행한다.

해당 코드에서 별표의 할당된 등급에서 사용자가 네번째 별을 탭하면 레시피의 등급이 4로 설정되며 다시 탭할 경우 별 없음으로 재설정이 된다.

3. 다른 view에 커스텀 컨트롤 표시

RegularTitleView.swift

import SwiftUI

struct RegularTitleView: View {
    @Binding var recipe: Recipe

    var body: some View {
        VStack(alignment: .leading) {
            Text(recipe.title)
                .font(.largeTitle)
            StarRating(rating: $recipe.rating)
        }
        Spacer()
        Text(recipe.subtitle)
            .font(.subheadline)
    }
}

1과 2를 거치면서 StartRating 을 만들었다.
필요한 데이터가 있고 변경 사항을 적용할 수 있으며 앱의 사용자 인터페이스에서 데이터의 현재 상태를 시각적으로 나타낼 수 있다.

3의 구조체는 등급과 함께 레시피의 제목과 부제를 표시하는 view이다.

참고자료

Method: onTapGesture()

기타

당연 틀린 부분 지적은 감사하나 비난은 정중하게 사양하겠다.

  • 아무리 봐도 이건 블로그를 포스팅 하는 것 보다는 내가 그냥 문서 읽으면서 이런거만 써놓으면 나중에 편하겠지 싶어서 쓰는것 같다.
  • 나중에 학습한 내용을 가지고 요약정리본을 만들 생각이다.
profile
"잘 할 수 있을까?"를 고민하기보단 재밌어 보이는건 일단 하고, 잘하기 위해 그냥 계속합니다.

0개의 댓글