0

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
        }
    }
}
Sulthan
  • 128,090
  • 22
  • 218
  • 270

2 Answers2

4

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 }
}
Luca Angeletti
  • 58,465
  • 13
  • 121
  • 148
  • Thank you! Should I use if let or dynamicType? –  Aug 20 '16 at 14:02
  • 1
    @appzYourLife issue #6 AnyObject is pretty much dead – matt Aug 20 '16 at 14:05
  • @matt what do you mean that AnyObject is pretty much dead? Why? and what should I use instead? –  Aug 20 '16 at 14:08
  • @AndreaMiotto: I believe _@matt_ means that the `UIKIt` methods are generics since Swift 2.0. E.g. `UIView().subviews` no longer returns `[AnyObject]`, it returns `[UIView]`. So in your code (outside of this function) you should probably use something like this `[UIView]` instead of `[AnyObject]`. – Luca Angeletti Aug 20 '16 at 14:34
  • @AndreaMiotto: I suggest you _Version #2_ or _Version #3_ – Luca Angeletti Aug 20 '16 at 14:36
  • 2
    @appzYourLife No, I mean that AnyObject is dead. Everything is Any now. Using AnyObject will cause your code to break because there is no longer any automatic bridging to AnyObject. So it's a good idea to get out of the habit of using AnyObject. (Of course, as you say, using UIView is a good idea in any case.) – matt Aug 20 '16 at 14:36
  • 2
    Also `dynamicType` is now `type(of:)`. – matt Aug 20 '16 at 14:38
  • 2
    Btw, *anything can* be bridged to AnyObject now: http://stackoverflow.com/questions/39033194/anyobject-not-working-in-xcode8-beta6. – Martin R Aug 20 '16 at 14:42
  • Thank you for all the suggestions. I also added the code for Swift 3.0 (beta 6). – Luca Angeletti Aug 20 '16 at 14:50
0

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
                }
            }
 }
Özgür Ersil
  • 6,909
  • 3
  • 19
  • 29