4

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)
        }
    }
}
JGE
  • 41
  • 3

5 Answers5

3

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

lorem ipsum
  • 21,175
  • 5
  • 24
  • 48
  • Wht do you really mean by `A struct is immutable`? – mahan Aug 06 '21 at 11:53
  • You can't change the pieces of a `struct` by default you can only change it as a whole. That is why SwiftUI has wrappers. https://medium.com/mobile-app-development-publication/use-swift-struct-for-total-immutability-6f07388cad5e – lorem ipsum Aug 06 '21 at 12:45
  • The wrappers control the changes of the pieces/parts of the SwiftUI `View`. – lorem ipsum Aug 06 '21 at 12:46
  • https://docs.swift.org/swift-book/LanguageGuide/ClassesAndStructures.html – lorem ipsum Aug 06 '21 at 12:50
  • @mahan A struct is not immutable per se - only if the struct value is itself constant. So, having a `let v = MyStruct()` which has `var name: String` does _not_ let you modify the name property of `v`. But a `var v = MyStruct()` is itself mutable, and thus its var properties can be mutated. In SwiftUI, you usually deal with constant Views, so having a `var somePorperty` is unusual. – CouchDeveloper Aug 06 '21 at 14:02
  • You can't change a `var` inside a SwiftUI `View` you need a SwiftUI wrapper to change it. The OP is talking in the context of a SwiftUI `View` – lorem ipsum Aug 06 '21 at 14:03
  • @CouchDeveloper Agree! – mahan Aug 06 '21 at 15:07
1

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.

vadian
  • 274,689
  • 30
  • 353
  • 361
1

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/

mahan
  • 12,366
  • 5
  • 48
  • 83
  • You will get an error trying to change `var name: String` that only works in a `class` from inside the `struct` such as in a SwiftUI `View` https://stackoverflow.com/questions/24035648/swift-and-mutating-struct – lorem ipsum Aug 06 '21 at 12:52
  • The question was targeted towards the context of parameters declared in `View` – Ray Tso May 04 '23 at 23:57
0

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.

  • `landmark` is initialized, see [Swift memberwise initializers](https://docs.swift.org/swift-book/LanguageGuide/Initialization.html#ID214). – George Aug 06 '21 at 09:29
  • If you read carefully, I meant it is initialized only when the struct LandmarkRow is initialized. I was more focused on differentiating let and var insider a Struct. My answer is quite similar to vadian's above. The compiler just won't know if it's modified before actually running the program. – Max_Level Aug 07 '21 at 01:11
0

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.