16
votes

At the line, dateFormatter.string(from: date), the compiler says:

Cannot use mutating getter on immutable value: 'self' is immutable
Mark method 'mutating' to make 'self' mutable

struct viewModel {
    
    private lazy var dateFormatter = { () -> DateFormatter in
        let formatter = DateFormatter()
        formatter.dateFormat = "MM/dd/yyyy"
        return formatter
    }()
    
    var labelText: String? {
        let date = Date()
        return dateFormatter.string(from: date)
    }
}

I understand what is written in this link, but the above situation is probably different.

Does anyone know how to get around this problem?

2
Why is it lazy in the first place? Do you really need lazy for creating a date formatter? - Sweeper
Lets just say my struct has many more properties and as creating DateFormatter is an expensive operation I want it to be lazy. - OutOnAWeekend
@AnandKumar Is it, though? - Alexander
@Alexander Creating NSDateFormatter did used to be expensive. chibicode.org/?p=41 - OutOnAWeekend
@AnandKumar Now imagine a more realistic situation where creating the date formatter is say, 5% of the work, then all of a sudden you'll notice that the relative time increase will be tiny - Alexander

2 Answers

21
votes

You need a mutating getter in order to perform mutations on self (such as accessing a lazy variable).

struct ViewModel {
    private lazy var dateFormatter = { () -> DateFormatter in
        let formatter = DateFormatter()
        formatter.dateFormat = "MM/dd/yyyy"
        return formatter
    }()

    var labelText: String? {
        mutating get {
            let date = Date()
            return dateFormatter.string(from: date)
        }
    }
}
1
votes

Accessing a lazy property on a struct mutates the struct to create the lazy property, same as if you were changing a var variable on that property.

So you are not allowed to use lazy var in any circumstance where re-assigning the var after init would not be allowed.

This is rather unintuitive, as using lazy var doesn't "feel" like it is mutating the struct after assignment. But when you think about it, that's exactly what's happening.