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.
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
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With