user4956851
user4956851

Reputation:

Swift: Why is this immutable?

Can you tell me why this code does not work?

I have several arrays of [AnyObject] that contain UILabels and UITextForm. This func should take as parameter an array and make all the labels and the text form disabled. I've tried with map, but still i have the same problem, the compiler tells me that or the variable is a constant or that is immutable.

func disableSectionForm(formSection section: inout [AnyObject]) {
    for i in 0...section.count {
        if section[i] is UILabel || section[i] is UITextField {
            section[i].isEnabled = false
        }
    }
}

Upvotes: 0

Views: 324

Answers (2)

Luca Angeletti
Luca Angeletti

Reputation: 59496

There are many compile errors here

Issue #1 (this is just a suggestion)

inout is not needed here because you are not mutating the section array, you are mutating the objects inside it instead.

Issue #2

The inout should go before the param name (if you are using Swift 2.2)

Issue #3

You should use self when comparing with dynamicType

Issue #4

You can't write section[i].isEnabled = false because AnyObject has no member isEnabled so you should do a cast

Issue #5

You are accessing an index outside of your array so this

0...section.count

should become this

0..<section.count

Code Version #1

Now your code looks like this

func disableSectionForm(formSection section: [AnyObject]) {
    for i in 0..<section.count {
        if section[i].dynamicType == UILabel.self {
            (section[i] as? UILabel)?.enabled = false
        } else if section[i].dynamicType == UITextField.self {
            (section[i] as? UITextField)?.enabled = false
        }
    }
}

Code Version #2

Since:

  1. you can iterate your elements in a safer way
  2. you should use conditional cast instead of dynamicType comparation

you can write in

Swift 2.2

func disableSectionForm(formSection section: [AnyObject]) {
    section.forEach {
        switch $0 {
        case let label as UILabel: label.enabled = false
        case let textField as UITextField: textField.enabled = false
        default: break
        }
    }
}

Swift 3.0 (beta 6)

func disableSectionForm(formSection section: [Any]) {
    section.forEach {
        switch $0 {
        case let label as UILabel: label.isEnabled = false
        case let textField as UITextField: textField.isEnabled = false
        default: break
        }
    }
}

Code Version #3

Let's define a protocol to represents classes with an enabled Bool property.

Swift 2.2

protocol HasEnabledProperty:class {
    var enabled: Bool { get set }
}

Let's conform to it UILabel and UITextLabel

extension UILabel: HasEnabledProperty { }
extension UITextField: HasEnabledProperty { }

And finally...

func disableSectionForm(formSection section: [AnyObject]) {
    section.flatMap { $0 as? HasEnabledProperty }.forEach { $0.enabled = false }
}

Swift 3.0 (beta 6)

protocol HasEnabledProperty:class {
    var isEnabled: Bool { get set }
}

extension UILabel: HasEnabledProperty { }
extension UITextField: HasEnabledProperty { }

func disableSectionForm(formSection section: [Any]) {
    section.flatMap { $0 as? HasEnabledProperty }.forEach { $0.isEnabled = false }
}

Upvotes: 4

&#214;zg&#252;r Ersil
&#214;zg&#252;r Ersil

Reputation: 7013

try to check if let block and use optionals

func disableSectionForm(formSection section: inout [AnyObject]) {
            for i in 0...section.count {
                if let label = section[i] as? UILabel {
                     label.isEnabled = false
                }
                if let textField = section[i] as? UITextFiled {
                     textField.isEnabled = false
                }
            }
 }

Upvotes: 0

Related Questions