SwiftUI: What is the difference between var and let as a parameter in List's Row?

Viewed 459

What is the difference between var and let as a parameter in List's Row?

Usually, if I don't change the landmark variable, the compiler will warn me, but there is no warning in that row. I wonder why.

struct LandmarkRow: View {
    var landmark: Landmark

    var body: some View {
        Text(landmark.id)
    }
}
struct LandmarkRow: View {
    let landmark: Landmark

    var body: some View {
        Text(landmark.id)
    }
}

This looks like a same result:

struct LandmarkList: View {
    var body: some View {
        List(landmarks, id: \.id) { landmark in
            LandmarkRow(landmark: landmark)
        }
    }
}
5 Answers

var is a variable meaning it is mutable. You can reassign it a value as many time as you wish.

In LandmarkRow and LandmarkList, var body is a computed property that calculates (rather than stores) a value. And it's read-only. Computed properties can only be declared using var.

When you implement a custom view, you must implement a computed body property to provide the content for your view. Return a view that's composed of primitive views that SwiftUI provides, plus other composite views that you've already defined. https://developer.apple.com/documentation/swiftui/view/body-swift.property

let is used to declare a constant. You can assign it a value exactly once as you have done in LandmarkList. In other words, you can not reassign it a value.

List(landmarks, id: \.id) { landmark in
     LandmarkRow(landmark: landmark)
}

Example


struct Example {
    // variable that you can change
    var name: String

    // constant that can only be assigned a value once.
    let fileExtension: String
    
    // A computed property that is read-only
    var filename: String {
        return name + "." + fileExtension
    }
}

var example = Example(name: "example", fileExtension: "swift")

You can change name from example to example_2 since it is a variable.

example.name = "example_2"

You can not change fileExtension from swift to js because fileExtension is a constant (let). If you do so, you will get the following error.

Cannot assign to property: 'fileExtension' is a 'let' constant

example.fileExtension = "js" 

You can not change fileName because it is a read-only property. If you try to change, you will get this error.

Cannot assign to property: 'filename' is a get-only property

example.filename = "ex.js"  

More info

What is the difference between `let` and `var` in swift?

https://docs.swift.org/swift-book/LanguageGuide/Properties.html

https://www.avanderlee.com/swift/computed-property/

The compiler warns you about local variables which are never been modified or being unused.

But you get never a warning about declared struct members / class properties. And a SwiftUI view is actually a regular struct.

However you get an error if you are going to modify a struct member / class property which is declared as constant.

In a SwiftUI View there is no difference except for semantics.

A struct is immutable therefore having a var vs a let is irrelevant.

let Is semantically correct

I am also new to SwiftUI. I only have backgound in C and C++. I am guessing that it has to do with the fact that you declared landmark but didn't initialized it (or in this case, default value). Here, it assumes that you will initialize landmark when you initialize a LandmarkRow. Getting back to the point, I think the compiler doesn't know if landmark changes or not untill it is run.

var => Variable

By defining var you inform the compiler that this variable will be changed in further execution of code.

var current_day = 6

let => Constant

By defining let you inform the compiler that this is a constant variable and its value stays the same. Like let earth_gravity = 9.8

Its just best practise to make unchanging variables constant. There will be no difference in execution of output.

Related