Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot assign value to stored property from within computed property

Tags:

swift

I created a struct in which I have a property '_photo' that is lazily assigned when the computed property 'photo' is called. I keep getting the error

Cannot assign to '_photo' in 'self'

Here is the code. I wrote the computed method in both Swift 1.1 (photo1) and swift 1.2 (photo2) syntax. Both give the same compile time error as noted above.

What changes are needed to fix that error?

import UIKit

public struct PhotoStruct {
    var _photo:UIImage?
    var urlString:String?

    init(image:UIImage?, url:String?){
        self._photo = image
        self.urlString = url

    }

    init(url:String?){
        self.urlString = url
    }


    var photo1:UIImage? {

        if let theURL = self._photo {
            return self._photo
        }else{
            if let urlString = self.urlString{
                if let url = NSURL(string: urlString as String){
                    if let imageData :NSData = NSData(contentsOfURL: url){
                        if let image:UIImage = UIImage(data:imageData){

                            self._photo = image //** Cannot assign error is here**
                        }
                    }
                }
            }
            return self._photo
        }
    }

    var photo2:UIImage? {

        if let theURL = self._photo {
            return self._photo
        }else{
            if let  urlString = self.urlString,
                    url = NSURL(string: urlString as String),
                    imageData :NSData = NSData(contentsOfURL: url),
                    image:UIImage = UIImage(data:imageData){

                            self._photo = image //** Cannot assign error is here**
            }
            return self._photo
        }
    }



}
like image 878
RMH Avatar asked Feb 17 '15 16:02

RMH


People also ask

Can we assign value to Computed property Swift?

You cannot assign a value to a computed property that doesn't have a setter. A few things to know: The set keyword makes the computed property writeable. Without it you get this error: Cannot assign to value [your computed property's name], it is a get-only property.

What is difference between stored properties and computed properties?

Stored properties store constant and variable values as part of an instance, whereas computed properties calculate (rather than store) a value. Computed properties are provided by classes, structures, and enumerations. Stored properties are provided only by classes and structures.

When might you use a computed property instead of a stored property?

Properties let us attach information to structs, and Swift gives us two variations: stored properties, where a value is stashed away in some memory to be used later, and computed properties, where a value is recomputed every time it's called.

How do you set a computed property in Swift?

To create computed properties, Swift offers you a getter and (an optional) setter method to work with. A getter method is used to perform a computation when accessing the property. A setter method is an optional method. It can be used to modify a property that relates to the computed property.


1 Answers

As for struct, If you want to mutate the self property inside computed properties, you have to explicitly declare the getter as mutating get { .. }

public struct PhotoStruct {
    var _photo:UIImage?
    var urlString:String?

    init(image:UIImage?, url:String?){
        self._photo = image
        self.urlString = url
    }

    init(url:String?){
        self.urlString = url
    }

    var photo1:UIImage? {
        mutating get {
    //  ^^^^^^^^^^^^
            // you can set `self._photo = image` here
        }
    }

    var photo2:UIImage? {
        mutating get {
    //  ^^^^^^^^^^^^
            // you can set `self._photo = image` here
        }
    }
}

Of course, the struct itself have to be mutable:

var pVar:PhotoStruct = PhotoStruct(image: nil, url: nil)
pVar.photo1 // no problem
let pLet:PhotoStruct = PhotoStruct(image: nil, url: nil)
pLet.photo1 // < [!] error: immutable value of type 'PhotoStruct' only has mutating members named 'photo1'

One caveat:

As far as I know, mutating get { } feature is undocumented on the language reference.

like image 145
rintaro Avatar answered Nov 12 '22 22:11

rintaro