如何为仅获取属性赋值

Posted

技术标签:

【中文标题】如何为仅获取属性赋值【英文标题】:how to assign value to a get-only property 【发布时间】:2021-11-13 22:16:55 【问题描述】:

正如电影结构如下所示,我想通过upVote 函数上传我的vote 保险库,但错误发生为“无法分配给属性:'vote' 是一个 get-only 属性”。

除了vote和'isFavored,其他属性都是从本地JSON文件解码出来的。

我的结构


struct Movie:Codable,Identifiable
    let id=UUID()
    let MOVIE_ID:String
    let NAME:String
    let ALIAS:String
    let ACTORS:String
    let COVER:String
    let DIRECTORS:String
    let DOUBAN_SCORE:String
    let DOUBAN_VOTES:String
    let GENRES:String
    let IMDB_ID:String
    let LANGUAGES:String
    let DIRECTOR_IDS:String
\\my own property:
    var isFavered:Bool = false
\\init the vote
    var vote:Int
        if let v = Int(DOUBAN_VOTES)
            return v
        else
            return 0
        
        
    
    enum CodingKeys: String, CodingKey 
        case MOVIE_ID, NAME,ALIAS,ACTORS,COVER,DIRECTORS,DOUBAN_SCORE
        case DOUBAN_VOTES,GENRES,IMDB_ID,LANGUAGES,MINS,OFFICIAL_SITE
        case REGIONS,RELEASE_DATE,SLUG,STORYLINE,TAGS,YEAR,ACTOR_IDS,DIRECTOR_IDS
    
\\my uploade vote function
    func upVote(newVote:Int)
        vote = newVote \\ here occurs the error
    


【问题讨论】:

关于我在你之前的问题中的评论:现在你已经添加了 CodingKeys,没有理由再使用丑陋的 UPPER_SNAKE_CASE 属性名称???? 是的,谢谢我也从另一个答案中得到了同样的建议????一旦我弄清楚如何更改属性的值,我将更改它们 您的问题似乎得到了回答,但您的回答是把它变成一个完全不同的问题? 是的,实际上我是几周前开始使用 *** 的,在这种情况下,我应该提出一个新问题吗? 我已回滚问题以匹配最初提出的问题和已回答的问题。请改为发布新问题。 【参考方案1】:

您首先需要将DOUBAN_VOTES 声明为可变,然后将计算属性更改为可变。通过将private(set) 用于 DOUBAN_VOTES,它将在结构之外是不可变的。

private(set) var DOUBAN_VOTES: String

var vote: Int 
  get 
    return Int(DOUBAN_VOTES) ?? 0
  
  set 
    DOUBAN_VOTES = String(newValue)
  

【讨论】:

感谢您的回答! DOUBAN_VOTE 可以保持为let 吗?比如将newValue 传递给vote 而不是DOUBAN_VOTE 不,此解决方案必须是可变的。也许最好寻找一个完全不同的解决方案,例如为投票创建一个新的结构或类,以便 Movie 结构都是不可变的。 好的,我试试,再次感谢!! 嗨,我添加了一个myMovie 类,如问题中所示。但是在测试页面上,当我单击投票按钮时,值没有改变。【参考方案2】:

你有两个问题。

首先,正如您所发现的,您不能修改vote,因为它是computed property。它的值由其 getter 方法中的代码确定。赋值没有意义。

我猜您使用了计算属性,因为坦率地说,您的 JSON 源很糟糕。整数应该作为整数发送,而不是字符串。

假设您无法将 JSON 更改为更合理的内容,那么您只需要更新 upVote 函数中的底层 DOUBAN_VOTES 属性即可。您需要将DOUBAN_VOTES 设为var,而不是let

这将揭示您的第二个问题;结构是不可变的。为了允许函数更改值,必须将其标记为 mutating 函数。


var DOUBAN_VOTES:String

mutating func upVote(newVote: Int) 
    self.DOUBAN_VOTES = "\(newVote)"

【讨论】:

感谢您的回答!确实,我的 JSON 源很糟糕,我不确定是否适合将我的 DOUBAN_VOTES 属性设置为 var,因为它是从文件中读取的。如果我更改数据,是否需要写回 JSON 文件?因为如果从文件中重新读取它的值不会改变。 将更新的数据写回服务器是完全不同的事情。是的,在典型的客户端/服务器应用程序中,您会将更改持久化回服务器。假设此时不在您的范围内,那么修改 DOUBAN_VOTES 属性没有问题,只需认识到您的更改不会被持久化,并且下次获取数据时它将是原始数据。此外,由于您已经麻烦添加了CodingKeys,您应该使用它们来制作 Swift 样式的属性名称。 感谢您的建议,我已更改属性名称并添加了一个新类以使其他属性可更改,并在我的问题中更新。但是我不知道为什么单击投票按钮时无法更改值 值在哪里没有变化?在结构上?在屏幕上?如果您正在谈论更改屏幕上的值,则需要编写在更改值时更新屏幕的代码。它不会自动发生。你用的是 UIKit 还是 SwiftUI? 我从您的回滚编辑中看到您正在使用 SwiftUI,因此您需要考虑使用合适的模型;一个 ObservableObject,例如

以上是关于如何为仅获取属性赋值的主要内容,如果未能解决你的问题,请参考以下文章

如何为起订量中的属性赋值?

我如何为 Apollo Client 指定 GraphQL 查询并获取属性出现适当字符串的项目

如何为有条件的必需属性实现客户端验证 - Razor ASP.NET 核心

如何为图像的 alt 属性设置样式

如何为 .h 中定义的属性在 .m 中为 Setter 和 Getter 自动生成 Xcode 5 代码? [复制]

如何为 UITabBarItem 设置自定义标题属性