카드를 왼쪽 혹은 오른쪽으로 넘길 때 카드 색을 다르게 표현해서 다른 의미를 지님을 보여줄 수 있다.
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
}
}