Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't change UIView.isHidden property after action is called by UIBarButton

Tags:

xcode

ios

swift

I am using UIView's isHidden property to show/hide controls on a posting interface I'm developing. I use this to change the controls available when the keyboard is up/down, post types are selected, etc. I have written a method triggered by notifications that sets the view properties (mainly .isHidden) and animates changes, which is called when the keyboard appears, or when the user selects a post type which then changes the controls available to them. This usually works perfectly fine, and the properties change as intended, but when the method is triggered by a UIBarButton action, the view being set to visible becomes unresponsive. After hitting bar button I am unable to change the isHidden property of the view (even by explicitly setting isHidden to true or false... it does not change).

Here is the method that changes the view properties:

@objc func animateActionViewChange(_ sender: Notification) {
        // DEBUG
        print("\n[BEFORE]\nnormalActionView.isHidden: \(normalActionView.isHidden)\nkeyboardActionView.isHidden: \(keyboardActionView.isHidden)\nkeyboardUp: \(keyboardUp)\nactionViewActive: \(actionViewActive)")

        // save prev state
        let normalTemp: Bool = normalActionView.isHidden
        let keyboardTemp: Bool = keyboardActionView.isHidden

        // set new state based on env vars
        normalActionView.isHidden = keyboardUp ? true : !actionViewActive
        keyboardActionView.isHidden = keyboardUp ? !actionViewActive : true

        // DEBUG
        print("[AFTER]\nnormalActionView.isHidden: \(normalActionView.isHidden)\nkeyboardActionView.isHidden: \(keyboardActionView.isHidden)\nkeyboardUp: \(keyboardUp)\nactionViewActive: \(actionViewActive)")

        // animate opacity changes
        if normalActionView.isHidden != normalTemp {
            let targetAlpha: CGFloat = normalTemp ? CGFloat(1) : CGFloat(0)

            UIView.animate(withDuration: actionViewAnimationDuration / 2) {
                self.normalActionView.alpha = targetAlpha
            }
        }

        if keyboardActionView.isHidden != keyboardTemp {
            let targetAlpha: CGFloat = keyboardTemp ? CGFloat(1) : CGFloat(0)

            UIView.animate(withDuration: actionViewAnimationDuration / 2) {
                self.keyboardActionView.alpha = targetAlpha
            }
        }
    }

and the action called by the UIBarButton (this issue concerns when the button title is 'back'):

// back/cancel button action
    @IBAction func cancel(sender: UIBarButtonItem) {
        if sender.title == "Cancel" {
            // cancel ongoing request if there is one
            if let request = ongoingRequest {
                if !request.isFinished {
                    request.cancel()
                }
            }

            self.performSegue(withIdentifier: "cancel_unwindFromNewPostView", sender: self)
        } else {
            // reset post type to default (general)
            postType = .general

            // set actionViewActive bool to set visibility going forwards
            actionViewActive = true

            // hide datePicker
            self.datePickerView.isHidden = true

            actionViewAnimationDuration = 0.35
            NotificationCenter.default.post(name: NSNotification.Name("animateActionViewChange"), object: nil)

            UIView.animate(withDuration: 0.35) {
                // layout
                self.view.layoutIfNeeded()
            }

            // revert button text to 'cancel'
            cancelButton.title = "Cancel"
        }
    }

Here is the output of the debugging flag before the 'back' button is hit:

[BEFORE]
normalActionView.isHidden: false
keyboardActionView.isHidden: true
keyboardUp: true
actionViewActive: true
[AFTER]
normalActionView.isHidden: true
keyboardActionView.isHidden: false
keyboardUp: true
actionViewActive: true

after:

[BEFORE]
normalActionView.isHidden: true
keyboardActionView.isHidden: true
keyboardUp: false
actionViewActive: true
[AFTER]
normalActionView.isHidden: true
keyboardActionView.isHidden: true
keyboardUp: false
actionViewActive: true

As you can see above, the isHidden property of the normal action view is not changing, even though it is being set to 'false'. I originally thought this was because a reference was being lost somewhere (though I thought that would result in a nil reference, which I don't have), so I made the references to normalActionView and keyboardActionView strong. This did not fix the problem, obviously, so I put the changes to isHidden in a method called by a notification to ensure it was always on the same thread (which it is, I checked by printing the current thread, it is always main), but that did not help either.

like image 803
Jai Avatar asked Dec 06 '22 09:12

Jai


1 Answers

isHidden behaves as though it is cumulative. For example, if you set it to true twice in a row, you would need to set it to false twice.

I usually use a check for the opposite value before setting a value.

if view.isHidden == false {
    view.isHidden = true 
}
like image 151
Chris Avatar answered May 24 '23 01:05

Chris