Ryan
Ryan

Reputation: 1465

Setting a computed value (struct vs class)

I made a simple struct that handles the management of the UI background (the user can choose to use a gradient or image). Inside this struct is a computed property called preference which gets and sets the user's preference to UserDefaults.

When I try to set the preference property using the following code:

Background().preference = .gradient

I get an error: "Cannot assign to property: function call returns immutable value"

I have to use this instead:

var background = Background() background.preference = .gradient

I would prefer not having to assign an instance of Background to a variable before finally setting the property.

I've found that changing Background from a struct to a class allows me to set the property using Background().preference = .gradient directly.

Can anyone give me some insight as to why this occurs? Is using class better than using struct for this situation or does it not matter?

struct Background {

enum Choice {
    case gradient
    case image
}

var preference: Choice {

    get {
        if let type = UserDefaults.standard.value(forKey: "background_type"), type as! String == "background" {
           return .image
        }
        return .gradient
    }

    set(value){
        if value == .image {
            UserDefaults.standard.setValue("background", forKey: "background_type")
        }else{
            UserDefaults.standard.setValue("gradient", forKey: "background_type")
        }
    }
}

Upvotes: 1

Views: 86

Answers (1)

user498982
user498982

Reputation:

You're not really getting any value from making an instance of a struct / class to just wrap UserDefaults. It's a very common problem and there are lots of clever solutions out there on google if you search around. For a really simple example you could just extend UserDefaults

//: Playground - noun: a place where people can play

import Cocoa


enum BackgroundChoice {
    case gradient
    case image
}

extension UserDefaults {

    var backgroundChoice: BackgroundChoice {
        get {
            if let type = string(forKey: "background_type"), type == "image" {
                return .image
            }
            return .gradient
        }

        set(value){
            if value == .image {
                setValue("background", forKey: "background_type")
            }else{
                setValue("gradient", forKey: "background_type")
            }
        }
    }

}

UserDefaults.standard.backgroundChoice = .image

I know this doesn't answer your exact question, but I think you'll find there are better solutions to this problem if you dig around.

Upvotes: 1

Related Questions