UIProgressView
UIProgressView는 0~1 사이의 수치로 progress를 표현할때 사용하는 UIView입니다.
개발자는 정확한 progress를 쉽게 표현하기 위해 UIProgressView를 사용할텐데요.
UIProgressView에는 숨겨진 함정이 있습니다.
바로 progress를 표현하는 최소 width가 정해져있다는 것입니다.
progress 수치에 따른 width 비교
0.5
예를 들어, width가 100인 UIProgressView의 progress를 0.5로 설정하면 progress width는 50이 됩니다.
progressView.progressTintColor = .cyan
progressView.frame = CGRect(x: 180, y: 300, width: 100, height: 8)
progressView.progress = 0.5
0.1
progress가 0.1이면 10이겠죠.
progressView.progress = 0.1
0.05
그럼 5%를 표현하기 위해 progress를 0.05로 설정하면 width가 5일까요?
아니오! 8입니다.
0 ~ 0.1
let progressViews: [UIProgressView] = Array(0...10).map { i in
let progressView = UIProgressView()
progressView.trackTintColor = .gray
progressView.progressTintColor = .cyan
progressView.frame = CGRect(x: 180, y: 300 + 20 * i, width: 100, height: 8)
progressView.progress = 0.01 * Float(i)
return progressView
}
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
progressViews.forEach { view.addSubview($0) }
}
0부터 0.1까지를 비교해보면 1%부터 8%까진 progress 표현이 동일하고 9%부터 progress가 증가합니다.
즉, progress를 표현하는 UIImageView의 width가 8 미만으로 작아지지 않는 것을 확인할 수 있습니다.
UIProgressView.Style에 따라 차이가 있다
위 내용은 UIProgressView.Style이 default일 때의 증상입니다.
progressViewStyle를 bar로 설정하면 min width가 달라집니다.
let progressView = UIProgressView(progressViewStyle: .bar)
bar 스타일일 때는 1% ~ 5%까지 5.33으로 width가 동일하고, 6%부터 6 width를 가집니다.
여전히 최소 width가 존재하지만 그나마 세밀하게 표현된다는 차이점이 있습니다.
마무리
이 포스팅은 QA팀의 "progress가 제대로 표현되지 않는거 같아요."라는 문의에서 시작되었습니다.
하지만 코드는 view.progress = progress 뿐이었죠. 잘못 설정될 가능성이 없었습니다.
코드보단 동료를 믿고 width를 확인해봤고 정말로 progress가 제대로 표현되지 않았습니다.
세상에 100%는 없다는걸 다시 한 번 느꼈고, 디테일한 이슈를 잡아주신 동료에게 감사함을 전했습니다.
그리고 UIProgressView를 제거하고 두 개의 UIView로 직접 progress를 표현했습니다.
공식 문서를 보니 관련 내용은 없었고, stack overflow에 질문이 하나 있더라고요.
"애플은 사용자에게 progress 상태를 보여주기 위해 임의로 표현할 수 있다"는 답변으로 어이 없으면서 애플다운 구현이라고 생각했습니다. (근데 적어는 해줘야죠... ㅠ)
그리고 min width가 8인 이유는
UIProgressView의 최소 progress width가 8px인 이유에 대해 정확한 공식 문서는 없지만, 이는 Apple의 디자인 철학과 관련이 있을 가능성이 높습니다. Apple의 Human Interface Guidelines에서는 사용자가 쉽게 볼 수 있는 최소한의 크기를 유지하는 것을 중요시합니다. 8px는 Retina 디스플레이에서 시각적으로 구분 가능한 최소 크기에 해당하며, Apple의 디자인 시스템에서 8의 배수를 기본 그리드로 사용하는 경향이 있습니다.또한 접근성 측면에서도 너무 작은 UI 요소는 사용자가 인식하기 어려울 수 있어, 최소한의 크기를 보장하는 것으로 보입니다.정확한 기술적 이유를 알고 싶으시다면 UIKit 소스 코드를 살펴보거나 Apple 개발자 포럼에서 질문해보시는 것이 도움이 될 수 있습니다.
- Claude
정확한 “공식 문서상의” 근거는 찾기 어려울 수 있지만, 내부 리셋블 이미지의 cap inset 값과 Apple의 디자인 가이드라인에서 비롯된 것으로 보는 것이 타당합니다. 이러한 이유들로 인해 UIProgressView는 진행률이 극히 적은 경우에도 최소 8px 이상의 width를 유지하여, 원래의 디자인 의도와 시각적 완성도를 보존하고 있습니다.
- GPT
AI의 도움을 받았습니다 (머쓱)
8px 규칙이라는 디자인 권장사항도 있으니 Claude가 더 신뢰가 가네요 ^^!
코드만 보고 100% 문제 없다!라고 확답하지 말고 항상 의심하고 동료를 믿읍시다.
감사합니다.
아직은 초보 개발자입니다.
더 효율적인 코드 훈수 환영합니다!
공감과 댓글 부탁드립니다.