14 Replies
      Latest reply on Jan 13, 2019 10:36 AM by Claude31
      ToAlt Level 1 Level 1 (0 points)

        Hello,

         

        in my current iOS Project I change the UIProgressView tintColor at runtime.

        When I use the same color it works great, but if I use 2 different colors e.g.

        "progress is less than 20 percent it becomes red else it stays in init color" it does not work.

         

        The bug is that when I change at runtime the progressTintColor the progress bar becomes rounded corners and the actual progress does not match the current progress value. As I discribed by using the same logic and do not use a different color than the initial one it works.

         

        Is this a known bug in iOS?

         

        Code example:

         

        func setBatteryProgress(value: Int) {
                batteryProgress.progress = Float(value) / 100
                if (batteryProgress.progress <= 0.2) {
                    self.batteryProgress.progressTintColor = UIColor.red
                   //when I use here same color as in the else block it works
                } else {
                    batteryProgress.progressTintColor = primaryColor
                   //when I use here same color as in the if block it works
                }
        }

         

        Strange behavior -> the progress is at a random value, and the left corner of the progress bar is rounded.

         

        Some has an idea about this?

         

        Greetings

         

        Tobias

        • Re: UIProgressView progressTintColor bug
          Claude31 Level 8 Level 8 (5,655 points)

          I created a viewController, with a UIProgressView, a UITextField to set the value. The textField Editing Did End and Did End on exit are both connected to the IBAction.

          I use setProgress to set the value, not directly the property (I think this is what makes the difference)

          Here the complete code. Tested, it works.

           

          class SecondViewController: UIViewController {
          
              @IBOutlet weak var progressIndicator: UIProgressView!
             
              @IBOutlet weak var progressField: UITextField!
             
              override func viewDidLoad() {
                  super.viewDidLoad()
              }
             
              @IBAction func setProgressValue(_ sender: UITextField) {
                 
                  if let value = Int(sender.text!) {
                      setBatteryProgress(value: value)
                  }
              }
             
              func setBatteryProgress(value: Int) {
                 // NOT USED  progressIndicator.progress = Float(value) / 100
                  progressIndicator.setProgress(Float(value) / 100, animated: true)
                  if (progressIndicator.progress <= 0.2) {
                      self.progressIndicator.progressTintColor = UIColor.red
                      //when I use here same color as in the else block it works
                  } else {
                      progressIndicator.progressTintColor = .blue // primaryColor
                      //when I use here same color as in the if block it works
                  }
              }
          
          }
          • Re: UIProgressView progressTintColor bug
            OOPer Level 7 Level 7 (4,875 points)

            I tried your code and worked as expected.

             

            Are you sure you call your `setBatteryProgress(value:)` only in the main thread?

              • Re: UIProgressView progressTintColor bug
                ToAlt Level 1 Level 1 (0 points)

                @OOPer

                I am not sure since the battery progress change value is triggered from a notification center - send/triggered by a singleton.

                But I also tried

                DispatchQueue.main.async...()

                 

                Even if I set the progress via value property not setProgress(), it works with same colors!

                This is the strange behavior in my case.

                 

                It is triggered via notification like this:

                    // Notification function called each time BLEDevice gets characteristc update
                    @objc func voltageUpdate(_ notificaiton:Notification) {
                        setBatteryProgress(value: BLEDevice.shared.voltage)
                        setBatteryText(value: BLEDevice.shared.voltage)
                    }

                 

                 

                EDIT: But I will try with setProgress asap.

                  • Re: UIProgressView progressTintColor bug
                    OOPer Level 7 Level 7 (4,875 points)

                    Any notification triggered in a non-main thread will invoke the notification handler in the non-main thread.

                    So, even if it does not solve all the issues, you should better think using `DispatchQueue.main.async {}` is mandatory.

                     

                        @objc func voltageUpdate(_ notificaiton:Notification) {
                            DispatchQueue.main.async {
                                self.setBatteryProgress(value: BLEDevice.shared.voltage)
                                self.setBatteryText(value: BLEDevice.shared.voltage)
                            }
                        }
                    
                    

                     

                    The result of updating UI controls in a non-main thread is unpredictable and works with same colors is one possible result.

                    You may have other parts to fix, but please be sure that all UI updates are done in the main thread.

                    • Re: UIProgressView progressTintColor bug
                      Claude31 Level 8 Level 8 (5,655 points)

                      Tested: it works in the sample code I attached, with

                      progressIndicator.progress = Float(value) / 100

                       

                      even if you loose the animation.

                        • Re: UIProgressView progressTintColor bug
                          ToAlt Level 1 Level 1 (0 points)

                          In a static scenario or the same VC it seems to work. When the UI update comes from notification center it hangs up like I described. It is a thread problem I guess. Since I tried DispatchQueue.main.async() in several code spots it has no effect.

                          Tried a lot of stuff now. It is not working with my intention. Have to find a workaround. Thanks for helping.

                           

                          Or could it be something with the constrains I set on the UIProgress View? When changing color rgb?

                           

                          EDIT:

                           

                          I did an Outlet Button in the same VC - onClick change progress tint color.

                          Result:

                          It is changing the color but the progress has now a left rounded corner as I described above.

                            • Re: UIProgressView progressTintColor bug
                              Claude31 Level 8 Level 8 (5,655 points)

                              Could you post the complete code of the VC where the progressView is ?

                                • Re: UIProgressView progressTintColor bug
                                  ToAlt Level 1 Level 1 (0 points)

                                  I came a step ahead by changing in the storyboard attribute inspector -> Progress View -> Style (here is set "Bar" now).

                                  Result: the left rounded corner of the progress is fixed now when changing the color of the progress.

                                   

                                  But by changing the color, the progress still is always set to a default "buggy value" by about 80 percent even log shows (my current value is correct)

                                   

                                  I also set in the storyboard force from left-to-right!

                                  • Re: UIProgressView progressTintColor bug
                                    ToAlt Level 1 Level 1 (0 points)
                                    @IBOutlet var batteryProgress: UIProgressView!

                                     

                                    in ViewDidLoad:

                                     

                                    setBatteryProgress(value: BLEDevice.shared.voltage)
                                    nc.addObserver(self, selector: #selector(voltageDidUpdate(_:)), name: Notification.Name("VoltageUpdate"), object: nil)

                                    Custom functions:

                                     

                                        // Notification function called each time BLEDevice gets characteristc update
                                        @objc func voltageDidUpdate(_ notificaiton:Notification) {
                                            // Make sure that it is Akku Mode
                                            if(BLEDevice.shared.pwrSupplyState == 1) {
                                                setBatteryProgress(value: BLEDevice.shared.voltage)
                                            }
                                        }
                                    
                                        func setBatteryProgress(value: Int) {
                                            batteryProgress.progress = Float(value) / 100
                                            if (batteryProgress.progress <= 0.2) {
                                                batteryProgress.progressTintColor = UIColor.red
                                            } else {
                                                batteryProgress.progressTintColor = primaryColor
                                            }
                                        }

                                     

                                    Fired test scenario from a different ViewController:

                                     

                                       BLEDevice.shared.voltage = 5
                                       nc.post(name: Notification.Name("VoltageUpdate"), object: nil)

                                     

                                    On loading first time (viewDidLoad) BLEDevice.shared.voltage value is 99 and shown correctly!

                                    When the test notification is triggered, the color changes but the progress is not set to 5% as it should be (the log shows it correctly 5%) it hangs up like 0.75 percentage progress.

                                     

                                    Last information I could share is that in the storyboard the progress TintColor is set to primary color. By launching my VC the color is first time "overwritten" (with the same color as in storyboard set) by

                                     

                                    batteryProgress.progressTintColor = primaryColor

                                     

                                    if I set there on first time (ViewDidLoad -> UIColor.red it is also shown correctly. Just on updating it, it buggs.

                                     

                                    The left corner bug is fixed as I described above by setting it to "Bar".

                                      • Re: UIProgressView progressTintColor bug
                                        Claude31 Level 8 Level 8 (5,655 points)

                                        Did you try, as avvised by OOPer

                                         

                                            func setBatteryProgress(value: Int) {
                                               DispatchQueue.main.async {
                                                     self.batteryProgress.progress = Float(value) / 100
                                                     if (self.batteryProgress.progress <= 0.2) {
                                                         self.batteryProgress.progressTintColor = UIColor.red
                                                     } else {
                                                         self.batteryProgress.progressTintColor = primaryColor
                                                     }
                                              }
                                            }