André Kuhlmann
André Kuhlmann

Reputation: 4668

Disable an array of UIButtons and UITextFields

What I'm trying to achieve is to disable all my elements on my login screen once the user has pressed the login button. I have created a simple function which keeps an array of all the elements that should be disabled.

func disableElements() {
    let elements: [AnyObject] = [usernameInput, passwordInput, loginBtn]

    for element in elements {
        element.isEnabled = false // ERROR: Cannot assign to property: 'element' is a 'let' constant
    }
}

I have found a similar question ("Cannot assign to property: "any" is immutable" error) where the OP was able to just change the array type from AnyObject to UIImageView, but what if there are different types in the array (like in my case UITextFields and UIButtons)?

Upvotes: 0

Views: 159

Answers (3)

Josh O'Connor
Josh O'Connor

Reputation: 4962

Create a boolean, ie: fileprivate var allowUserToInteractWithElements = true, and when the login button is pressed set this to false.

In your IBAction for your button, and in the UITextfieldShouldBeginEditing delegate method, use this boolean as conditional. This is a better way to handle disabling of buttons/textfields in my opinion.

Ex:

@IBAction func buttonPressed(_ sender: Any) {
    if (allowUserToInteractWithElements) {
    //Do action
    }
}

func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
    if (allowUserToInteractWithElements) {
        return false
    }else{
        return true
    }
}

Upvotes: 0

Sweeper
Sweeper

Reputation: 271820

where he was able to just change the array type from AnyObject to UIImageView, but what if there are different types in the array (like in my case UITextFields and UIButtons

Well, if there are different types of stuff in an array, you just need to find the nearest common ancestor of all the types. By common ancestor, I mean the superclass that both classes inherit from.

In this case, you have UITextField and UIButton. Their nearest ancestor is UIControl, which has the isEnabled property.

enter image description here

Therefore, you should use UIControl as the type of the array.

func disableElements() {
    let elements: [UIControl] = [usernameInput, passwordInput, loginBtn]

    elements.forEach { $0.isEnabled = false }
}

Here are the "Relationships" section for UIButton and UITextField:

https://developer.apple.com/documentation/uikit/uibutton#relationships

https://developer.apple.com/documentation/uikit/uitextfield#relationships

Upvotes: 3

rmaddy
rmaddy

Reputation: 318824

The isEnabled property is from UIControl. Both UIButton and UITextField extend UIControl. So make your array an array of UIControl instead of an array of AnyObject.

func disableElements() {
    let elements: [UIControl] = [usernameInput, passwordInput, loginBtn]

    for element in elements {
        element.isEnabled = false
    }
}

Upvotes: 2

Related Questions