89: Flashzilla, part 4

그루두·2024년 8월 17일
0

100 days of SwiftUI

목록 보기
97/108

Project 17, part 4

swipe 방향에 따라 다르게 표현하기

카드를 왼쪽 혹은 오른쪽으로 넘길 때 카드 색을 다르게 표현해서 다른 의미를 지님을 보여줄 수 있다.

            RoundedRectangle(cornerRadius: 25)
                .fill(
                    .white
                        .opacity(1 - Double(abs(offset.width / 50)))
                )
                .background(
                    RoundedRectangle(cornerRadius: 25)
                        .fill(offset.width > 0 ? .green : .red)
                )
                .shadow(radius: 10)

커밋 링크

그러나! 색맹인 사용자를 위해 색상이 아닌 다른 요소로 구분하기 모드에서 색이 아닌 이모지로 대신 표현했다.

커밋 링크

앱이 활성화 되어 있을 때 타이머 실행하기

100초 제한시간을 타이머로 설정하고 화면에 나타냈다.

    @State private var timeRemaining = 100
    let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
        .onReceive(timer) { time in
            guard isActive else { return }
            if timeRemaining > 0 {
                timeRemaining -= 1
            } else {
                
            }
        }

여기서 타이머가 실행되고 있는 와중에 홈으로 나갔다가 다시 돌아오면 나가기 전의 남은 시간과 2, 3초 정도 차이가 있음을 발견할 수 있다. 그래서 앱이 활성화 상태일 때만 타이머가 작동하도록 설정해주어야 한다.

이는 scenePhase로 앱의 상태를 확인하여 수정할 수 있다.

@Environment(\.scenePhase) var scenePhase
@State private var isActive = true
        .onReceive(timer) { time in
            guard isActive else { return }
            if timeRemaining > 0 {
                timeRemaining -= 1
            } else {
                
            }
        }
        .onChange(of: scenePhase) {
            if scenePhase == .active {
                isActive = true
            } else {
                isActive = false
            }
        }

커밋 링크

시간이 끝나거나 카드를 다 넘겼을 때 설정하기

시간이 끝나면 카드 넘기기를 제한하고, 시간이 끝나기 전에 카드를 다 넘기면 다시 시작할 수 있는 버튼을 보여준다.

// 카드 스택
.allowsHitTesting(timeRemaining > 0)

// 카드가 비면
                if cards.isEmpty {
                    Button("Reset cards", action: resetCards)
                        .font(.title)
                        .padding()
                        .foregroundStyle(.black)
                        .background(.white.opacity(0.7))
                        .clipShape(.capsule)
                }

그리고 카드가 더이상 없을 때 타이머가 멈추도록, 카드가 리셋되도록 함수를 설정했다.

    func removeCard(at index: Int) {
        cards.remove(at: index)
        if cards.isEmpty {
            isActive = false
        }
    }
    func resetCards() {
        cards = Array<Card>(repeating: .example, count: 10)
        isActive = true
        timeRemaining = 10
    }

이때 카드를 모두 넘겨서 타이머가 멈췄는데, 앱을 나갔다가 다시 들어옴으로써 isActive가 활성화되어 타이머가 다시 활성화 되지 않게 아래처럼 설정해야 한다.

        .onChange(of: scenePhase) {
            if scenePhase == .active && !cards.isEmpty {
                isActive = true
            } else {
                isActive = false
            }
        }

커밋 링크

profile
계속 해보자

0개의 댓글

관련 채용 정보