[iOS] UIProgressView 이슈

승아·2021년 9월 2일
0

위의 사진을 보면 12의 값을 받았지만 progressView가 대략 21정도의 값을 나타낸다. progressView가 21 보다 큰 값과 0의 값은 제대로 나타내지만 21 보다 작은 값은 나타내지 못하는 문제가 발생했다.

우선 문제를 해결하기 전 코드는 이렇다.

override func viewDidLoad() {
  super.viewDidLoad()

  configureProgressView()
  
  fineDustViewModel.observable
    .observe(on: MainScheduler.instance)
    .subscribe(onNext:{ [weak self] in
      self?.setProgressView($0)
    })
    .disposed(by: disposeBag)
}

private func configureProgressView(){
  fineDustProgressView.progressViewStyle = .bar
  fineDustProgressView.trackTintColor = #colorLiteral(red: 0.835541904, green: 0.8356826901, blue: 0.8355233073, alpha: 1)
  fineDustProgressView.clipsToBounds = true
  fineDustProgressView.layer.cornerRadius = 15
  fineDustProgressView.layer.sublayers![1].cornerRadius = 15
  fineDustProgressView.subviews[1].clipsToBounds = true
  fineDustProgressView.progress = 0.0
}

viewDidLoad에서 configureProgressView()를 호출한다. configureProgressView() 함수는 ProgressView를 꾸며주는? 함수이다. 그리고 obsevable을 통해 미세먼지의 값을 받고 setProgressView() 함수를 호출한다.

setProgressView()함수는 아래와 같다.

private func setProgressView(_ fineDustAPIData: FineDustAPIData){
  timer?.invalidate()
  time = 0.0
  fineDustProgress = fineDustViewModel.calculatorFineDustValue(fineDustAPIData.fineDust.fineDustValue)
  fineDustProgressView.progressTintColor = fineDustAPIData.fineDust.fineDustColor
  
  timer = Timer.scheduledTimer(timeInterval: 0.05, target: self, selector: #selector(setProgress(sender:)), userInfo: nil, repeats: true)
}

@objc func setProgress(sender: Timer) {
  time += 0.01
  
  if time <= fineDustProgress{
    fineDustProgressView.setProgress(time, animated: true)
  }

  if time > fineDustProgress {
    time = 0.0
    timer?.invalidate()
  }
}

여기서 fineDustProgressView의 progressTintColor를 변경하고 timer를 생성한 후 생성한 timer를 통해 setProgress함수를 실행하여 progressView의 Animation을 custom 하였다.

코드상 문제가 없다고 생각했지만 위와 같은 문제가 계속 발생했다.

문제의 원인은 setProgressView()함수에서 fineDustPrgoressView의 prgoressTintColor를 변경하는 부분이었다. 이 부분을 주석처리하니 21 보다 작은 값도 제대로 나타냈다.

private func setProgressView(_ fineDustAPIData: FineDustAPIData){
  timer?.invalidate()
  time = 0.0
  fineDustProgress = fineDustViewModel.calculatorFineDustValue(fineDustAPIData.fineDust.fineDustValue)
  // 문제 원인 !!
  fineDustProgressView.progressTintColor = fineDustAPIData.fineDust.fineDustColor
  
  timer = Timer.scheduledTimer(timeInterval: 0.05, target: self, selector: #selector(setProgress(sender:)), userInfo: nil, repeats: true)
}

하지만 나는 미세먼지의 데이터를 받아와 좋음, 보통, 나쁨과 같이 세가지의 상태에 따라 progressView의 tintColor를 바꿔줘야 했다.

여러 시도를 해본 결과 configureProgressView()를 viewDidLoad()에서 실행하지 않고 setProgressView() 에서 실행시켜 문제를 해결할 수 있었다.

private func configureProgressView(){
  fineDustProgressView.progressViewStyle = .bar
  fineDustProgressView.trackTintColor = #colorLiteral(red: 0.835541904, green: 0.8356826901, blue: 0.8355233073, alpha: 1)
  fineDustProgressView.clipsToBounds = true
  fineDustProgressView.layer.cornerRadius = 15
  fineDustProgressView.layer.sublayers![1].cornerRadius = 15
  fineDustProgressView.subviews[1].clipsToBounds = true
  fineDustProgressView.progress = 0.0
}

private func setProgressView(_ fineDustAPIData: FineDustAPIData){
  timer?.invalidate()
  time = 0.0
  fineDustProgress = fineDustViewModel.calculatorFineDustValue(fineDustAPIData.fineDust.fineDustValue)
  
  configureProgressView() // 여기에 추가 !!!!
  fineDustProgressView.progressTintColor = fineDustAPIData.fineDust.fineDustColor
  
  timer = Timer.scheduledTimer(timeInterval: 0.05, target: self, selector: #selector(setProgress(sender:)), userInfo: nil, repeats: true)
}

문제를 해결하였지만 configureProgressView()를 계속 호출하는건 낭비라고 생각하고 configureProgressView() 함수에 어떤 코드가 정상적인 결과를 출력하는지 찾아보았다.

찾아보니 prgoressViewStyle을 정의하는 fineDustProgressView.progressViewStyle = .bar 코드와 progressTintColor를 바꾸는 코드가 같이 호출되야 정상적인 결과를 출력하는걸 알게 되었다.

최종 코드는 아래와 같다.

override func viewDidLoad() {
  super.viewDidLoad()
  // configureProgressView()는 viewDidLoad에서 호출
  configureProgressView()
  
  fineDustViewModel.observable
    .observe(on: MainScheduler.instance)
    .subscribe(onNext:{ [weak self] in
      self?.setProgressView($0)
    })
    .disposed(by: disposeBag)
}

private func configureProgressView(){
  fineDustProgressView.trackTintColor = #colorLiteral(red: 0.835541904, green: 0.8356826901, blue: 0.8355233073, alpha: 1)
  fineDustProgressView.clipsToBounds = true
  fineDustProgressView.layer.cornerRadius = 15
  fineDustProgressView.layer.sublayers![1].cornerRadius = 15
  fineDustProgressView.subviews[1].clipsToBounds = true
  fineDustProgressView.progress = 0.0
}

private func setProgressView(_ fineDustAPIData: FineDustAPIData){
  timer?.invalidate()
  time = 0.0
  fineDustProgress = fineDustViewModel.calculatorFineDustValue(fineDustAPIData.fineDust.fineDustValue)
  
  // progressViewStyle과 TintColor를 같이
  fineDustProgressView.progressViewStyle = .bar
  fineDustProgressView.progressTintColor = fineDustAPIData.fineDust.fineDustColor
  
  timer = Timer.scheduledTimer(timeInterval: 0.05, target: self, selector: #selector(setProgress(sender:)), userInfo: nil, repeats: true)
}

여기서 주의할 점은 configureProgressView()에서 fineDustProgressView.progressViewStyle = .bar 코드는 지워주고 prgoressViewStyle은 꼭 .bar로 설정해줘야 된다.

https://stackoverflow.com/questions/54148264/uiprogressview-setprogress-issue 를 보니 나와 같은 오류가 발생하는 경우가 있어 글을 써보았지만 무엇이 제대로된 원인인지는 파악하지 못했다..😅

해결하지 못한 의문점은 이렇다 .. 아시는 분은 댓글 달아주세요 😂

  1. setProgressView() 함수를 비동기로 데이터를 받은 후 실행시키지 않고 그냥 viewDidLoad()에서 실행시키면 위와 같이 코드를 변경하지 않아도 progressView가 정상적으로 출력된다.
  2. progressViewStyle이 .default일 경우 정상적으로 출력되지 않는다.

0개의 댓글