스택뷰안에 몰아넣고
그래프막대를 하나의 뷰로 만든다음 계속 재사용하는 방식
애니메이션이 안되길래 mainAsync > 애니메이션은 되지만 막대그래프를 기준으로 잡은 레이블들 때문에 레이아웃이 랜덤해짐 ㅋㅋ
생각해보니 반복되는 요소들인데 뭐하러 하나하나 잡았지?
컬렉션뷰로 다시 만든다..
수정전
func setProgress(_ progress: CGFloat) {
layoutIfNeeded()
let targetProgress = min(max(progress, 0), 1)
UIView.animate(withDuration: 0.9, delay: 0.5, options: [.curveEaseInOut], animations: {
self.progressWidthConstraint?.update(offset: self.bounds.width * targetProgress)
self.layoutIfNeeded()
}, completion: nil)
}
수정 후
func setProgress(_ progress: CGFloat) {
DispatchQueue.main.async {
self.layoutIfNeeded()
let targetProgress = min(max(progress, 0), 1)
UIView.animate(withDuration: 0.9, delay: 0, options: [.curveEaseInOut], animations: {
self.progressWidthConstraint?.update(offset: self.bounds.width * targetProgress)
self.layoutIfNeeded()
}, completion: nil)
}
}
이 문제는 레이아웃 타이밍과 관련이 있었다. setProgress
메서드가 호출될 때 뷰의 레이아웃이 완전히 설정되지 않은 상태였을 가능성이 높다. DispatchQueue.main.async
를 사용하여 메인 스레드의 다음 런 루프까지 실행을 지연시킴으로써, 우리는 레이아웃 사이클이 완료된 후에 애니메이션을 시작할 수 있게 되었다. 이는 Auto Layout이 뷰의 크기와 위치를 계산하고 적용할 충분한 시간을 가질 수 있게 해준다. 또한, 애니메이션 지연을 0으로 설정하여 화면 전환 직후 즉시 애니메이션이 시작되도록 했다. 결과적으로, 뷰의 초기 레이아웃이 완전히 설정된 상태에서 애니메이션이 시작되어 의도한 대로 부드럽게 동작하게 된다.