0

I have two variables isLoading and isConnected in a UITableViewCell class and the code is as below:

    var isConnected = false {
        didSet {
            if oldValue != isConnected {
                print("[op] isConnected: \(oldValue) -> \(isConnected)")
                updateActionButton()
            }
        }
    }
    private var isLoading = false {
        didSet {
            if oldValue != isLoading {
                print("[op] isLoading: \(oldValue) -> \(isLoading)")
                updateLoadingView()
            }
        }
    }
...
    private func updateActionButton() {
        print("[op] updateActionButton()")
        actionButton.setTitle(isConnected ? "Disconnect" : "Connect", for: .normal)
        actionButton.setTitleColor(isConnected ? .systemRed : .systemBlue, for: .normal)
        print("[op] \(isConnected ? "Disconnect" : "Connect") : \(actionButton.isHidden ? "hidden" : "show")")
    }
    private func updateLoadingView() {
        loadingIndicator.isHidden = !isLoading
        actionButton.isHidden = isLoading
        if isLoading {
            loadingIndicator.startAnimating()
        } else {
            loadingIndicator.stopAnimating()
        }
    }

The logic is very simple:

  • When isLoading == true, the cell will display the loadingIndicator which is a UIActivityIndicatorView.

  • When isLoading == false, it will hides the loadingIndicator and show the actionButton.

  • When the cell receives a notification, it will change the value of isLoading and isConnected, the code it triggers is:

isConnected = true
isLoading = false

The expected behavior is:

  • step 1: The text of button change to Disconnect. (the button is hidden at this time)
  • step 2: loadingIndicator is set to hidden and actionButton appears with text Disconnect.

However, what it really happens at step 2 is:

actionButton appears with text Connect and then the text changes to Disconnect.

And the console log is:

[op] isConnected: false -> true
[op] updateActionButton()
[op] Disconnect : hidden
[op] isLoading: true -> false

The order I got from console is correct, the setTitle function was called before isLoading changed to false, but I don't know why the text is still Connect when the actionButton.isHidden is set to false.

So I wonder is setTitle asynchronous (the function is not complete when actionButton is set to not hidden)? Or there is something wrong in my code logic to cause the unexpected behavior in step 2?

Compound07
  • 143
  • 2
  • 8
  • `setTitle(_,for:)` is synchronous, so you need to do more debugging: is the referenced button _really_ the button you expect to modify? (For example, test by changing the strings you assign to something completely different, set break points and look at the instance, etc.). Is there some other code that might change the button? – DarkDust Jul 12 '22 at 06:42
  • may be the button state is causing the issue. try to set state to .normal , .selected , .highlighted at same time. – Vikas saini Jul 12 '22 at 06:49
  • Also , try to set title on main thread. – Vikas saini Jul 12 '22 at 06:51
  • Another possibility is that the cell is accidentally reloaded, for example, if you have a reloadData somewhere in your code. A cell can also be reloaded upon scrolling, when it moves out and into the screen – Arik Segal Jul 12 '22 at 07:31
  • Thank you all. I've managed to find the reason. https://stackoverflow.com/questions/18946490/how-to-stop-unwanted-uibutton-animation-on-title-change Turns out this happened since iOS 7 but I've never encountered this since today. The button I create is a `system` type, so either I change it to a `custom` type or I use the solution in that question. – Compound07 Jul 12 '22 at 07:45

0 Answers0