Difference Between Computed Property and Property Set With Closure

Difference between computed property and property set with closure

In short, the first is a stored property that is initialized via a closure, with that closure being called only one time, when it is initialized. The second is a computed property whose get block is called every time you reference that property.


The stored property’s initialization closure is called once and only once, but you can later change the value of the stored property (unless you replace var with let). This is useful when you want to encapsulate the code to initialize a stored property in a single, concise block of code.

The computed property’s block, however, is called each time you reference the variable. It’s useful when you want the code to be called every time you reference the computed property. Generally you do this when the computed property needs to be recalculated every time you reference the stored property (e.g. recalculated from other, possibly private, stored properties).

In this case, you undoubtedly want the stored property (the first example), not the computed property (the second example). You presumably don't want a new push behavior object each time you reference the variable.


By the way, in your first example, you internally reference to it being instantiated lazily. If you want that behavior, you must use the lazy keyword:

lazy var pushBehavior: UIPushBehavior = {
let behavior = UIPushBehavior()
behavior.setAngle(50, magnitude: 50)
return behavior
}()

If, however, the property is static, it is automatically instantiated lazily.

Difference between computed property and property set with closure in swift 3?

There is no difference.

From the documentation

You can simplify the declaration of a read-only computed property by removing the get keyword and its braces.

difference between a computed property and setting a function to a variable in Swift

The code in the computed property gets executed every time you reference that variable. The code in the property initialized by a closure is only executed once, during initialization.

Computed property of closures

Closures (and functions) are advertised as first class citizens in swift, so you can store them in variables and properties like any other data type.

That said, your code is almost good, you just have to remove the '=' because otherwise it's considered as a stored property with inline initialization. The correct code is:

var myAction:myFuncType {
set(newAction) {
self._myAction = newAction
}
get { // see notes below
return _myAction
}
}

Some notes:

  • there's no need to use a computed property backed by a stored property - your code is equivalent to:

    class MyClass {
    typealias myFuncType = () -> (Void)

    var myAction: myFuncType
    }
  • if you need to make additional processing when setting the property, make use of Property Observers: willSet and didSet

  • in a computed property, if you implement a setter, you must also provide a getter

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

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.

Is it complusory to use in keyword in closure? If no then what is the syntax wise difference between closure and computed property in swift?

greet is a closure. A computed property is

var greet : Int {
return 4+3
}

greet // without parentheses

And "in" in closure is also not compulsory if a parameter is passed (by the way the return keyword is not compulsory)

var greet = { x in
4+x
}

greet(4)

unless you use the shorthand syntax

var greet = {
4+$0
}

greet(4)

What is the difference between the following 3 declarations?

1.

var title: UILabel {
let label = UILabel()
textLabel.font = .systemFontOfSize(13)
return label
}

It is a read only computed property. Computed properties cannot be let. These are calculated using other stored/computed properties. So they don't have any backing store of their own. Hence, computed properties are always declared as var.

2.

let title: UILabel = {
let label = UILabel()
textLabel.font = .systemFontOfSize(13)
return label
}()

It is a stored property. This is assigned a closure that returns a UILabel object. This closure is executed during the instantiation process of the object and the returned UILabel object is assigned to title.

3.

lazy var title: UILabel = {
let label = UILabel()
textLabel.font = .systemFontOfSize(13)
return label
}()

It is a lazy stored property. It is also assigned a closure that returns a UILabel object. But this closure is not executed during the instantiation process. It is executed whenever this property is first used. After the execution of the closure, the UILabel object returned is assigned to title.



Related Topics



Leave a reply



Submit