Unable to assign value to saved property from computed property

I created a structure in which I have the "_photo" property, which is lazily assigned when the computed "photo" property is called. I keep getting an error

Unable to assign '_photo' to 'self'

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

What changes are needed to correct this 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 } } } 
+6
source share
3 answers

As for struct , if you want to change the self property inside the computed properties, you must explicitly declare 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 structure itself must be volatile:

 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 warning :

As far as I know, the mutating get { } function is mutating get { } documented in the language help system .

+10
source

Structs are value types, and they are immutable.
This means that you cannot set a variable and mutate yourself.
If you need to mutate a structure, you must make mutating func

 public struct PhotoStruct { var _photo:UIImage? var urlString:String? mutating func loadPhoto() -> UIImage { .. Code here _photo = UIImage(data:imageData) // Here you mutate a struct, but it ok because we make method as mutating } } 

In your example, I would make a mutating method instead of a property

 mutating func photo () -> UIImage? { if let photo = self._photo { return photo } else { if let urlString = self.urlString, url = NSURL(string: urlString), imageData = NSData(contentsOfURL: url), image = UIImage(data:imageData) { self._photo = image } return self._photo } } 
+4
source

PhotoStruct is a struct and therefore a value type. For value types, only methods explicitly marked as mutating can change properties from self , so this is not possible within the calculated property.

If you change PhotoStruct to class , then your code compilation is no problem.

+3
source

Source: https://habr.com/ru/post/982614/


All Articles