Search code examples
swiftclosurescomputed-properties

What is best practice, to enclose the value of a UITextField in a Computed property or in a Closure


If you have a UITextField and you know you will constantly reference its value and you will use the value as a Double which of the following two samples make more sense? Or better yet, does any of the two make sense? Is this a good practice to follow?

Computed Property

var fieldValue:Double {
    get{
        return Double(someField.text! ?? "0") as! Double
    }   
}

Store Property as Closure

var fieldValue:Double = {
    return Double(someField.text! ?? "0") as! Double
}()

Solution

  • The second option is NOT going to update constantly. Since it's not stored as a closure! It stored using a closure just once.

    So in this question, you have only the first option as a choice.

    Some helpful notes:

    1. Force unwrapping and using nil coalescing operator at same time is nonesence:
    Double(someField.text! ?? "0") // exclamation mark is nonesense here
    
    1. In get-only computed properties, you can get rid of the get keyword:
    var fieldValue: Double {
        return Double(someField.text ?? "0") as! Double
    }
    
    1. You don't need to forcecast a Double to Double:
    var fieldValue: Double {
        return Double(someField.text ?? "0")!
    }
    
    1. Since Swift 5.1, you don't need return keyword for single line expressions:
    var fieldValue: Double { Double(someField.text ?? "0")! }
    
    1. Seems like you need a 0 as a default value if initializer failed to initialize a Double from the text, right?! So replace the force unwrap with a default value as well:
    var fieldValue: Double { Double(someField.text ?? "0") ?? 0 }
    
    1. As @Dávid Pásztor mentioned and referenced, It is safe to force unwrap UITextField().text, so someField.text ?? "0" is just as useless as someField.text! ?? "0", since UITextField.text is guaranteed to be non-nil, it is only Optional due to Obj-C legacy support. So it could if you are not referencing an Obj-C, you can use it like:
    var fieldValue: Double { Double(someField.text!) ?? 0 }
    
    

    Other options:

    You can use valueChanged event of the textField to get notified and react in a function if you want:

    // Somewhere soon like `viewDidLoad`
        someField.addTarget(self, action: #selector(someFieldChanged(_:)), for: .valueChanged)
        }
        
        @objc private func someFieldChanged(_ sender: UITextField) {
            let fieldValue = Double(sender.text ?? "0") ?? 0
            ,,,
        }
    

    Also you can use delegate methods for this. It's up to you.