【问题标题】:Struct's id of type UUID changes everytime i try to access it [duplicate]每次我尝试访问它时,结构的 UUID 类型的 id 都会发生变化[重复]
【发布时间】:2021-10-15 17:30:18
【问题描述】:

我有一个从 JSON 解析的结构,但包含另一个必须可识别的结构 Article。它看起来像这样:

import Foundation

struct TopHeadlines: Codable {
    var totalArticles: Int
    var articles: [Article]

    struct Article: Codable {
        var title: String
        var description: String
        var url: String
        var image: String
        var publishedAt: String
        var source: Source
    }
    
    struct Source: Codable {
        var name: String
        var url: String
    }
    
    var json: Data? {
        return try? JSONEncoder().encode(self)
    }

}

extension TopHeadlines.Article: Identifiable {
    var id: UUID { return UUID() }
}

我需要生成 UUID 来访问 newImages 字典中的图像:

List(viewModel.articles, id: \.id) { article in
                    HStack {
                        OptionalImage(uiImage: viewModel.newsImages[article.id])
                        Text(article.id.uuidString)
                        Text(article.id.uuidString)
                        Text(article.id.uuidString)

                    }
                }

但是三个文本视图会打印三个不同的 UUID:

CC83B8AE-61B1-4A7D-A8A4-1B1E98C27CE7
545C1D28-F098-48A3-8C3C-A98BB54F9751
39B8383C-A2D8-46B0-BA51-1B861AF09762

我应该如何为Article struct 创建 ID,这样它就不会每次都重新生成?

【问题讨论】:

  • 那个id属性是一个计算属性,所以每次访问它都会返回一个全新的UUID。

标签: swift struct uuid


【解决方案1】:

您的扩展中的id 属性是一个计算属性,因此每次调用都会生成一个新的 UUID (UUID())。

由于您不能在扩展中存储属性,请尝试将其直接添加到 Article 结构中,如下所示:

struct Article: Codable, Identifiable {
    var id = UUID()
    var title: String
    var description: String
    var url: String
    var image: String
    var publishedAt: String
    var source: Source
}

这只会在结构初始化时生成一个 UUID。

【讨论】:

    【解决方案2】:

    您已将id 声明为计算属性,因此根据定义,每次访问该属性时都会返回一个新的UUID 实例。

    您需要将该属性设置为存储的不可变属性,以确保UUID 永远不会更改。

    您还需要手动声明一个符合CodingKeyenum 并在其大小写中省略id 键,以告诉编译器不应从JSON 中解码id

    struct TopHeadlines: Codable {
        var totalArticles: Int
        var articles: [Article]
    
        struct Article: Codable, Identifiable {
            var title: String
            var description: String
            var url: String
            var image: String
            var publishedAt: String
            var source: Source
    
            let id = UUID()
    
            private enum CodingKeys: String, CodingKey {
                case title, description, url, image, publishedAt, source
            }
        }
    
        struct Source: Codable {
            var name: String
            var url: String
        }
    
        var json: Data? {
            return try? JSONEncoder().encode(self)
        }
    }
    

    【讨论】:

      【解决方案3】:

      扩展不能存储属性,这就是为什么您将id 实现为计算属性,并且每个新的UUID() 都是唯一的

      最明显的解决方案是将它移动到你的结构中

      struct Article: Codable {
          let uuid = UUID()
          // ...
      }
      

      这样声明它在解码或创建新对象时都不需要值。


      但是如果你不能编辑这个结构(这可能是你使用扩展的原因),你可以做以下事情:用Hashable扩展你的结构,然后你可以访问对象hashValue,这是计算出来的基于所有属性,因此该值仅对于所有属性中具有相同值的两个对象是相同的,这通常适合唯一标识符

      extension Article: Hashable {
          
      }
      

      用法

      Text("\(article.hashValue)")
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-02-15
        • 2021-02-11
        • 2020-05-19
        • 2018-04-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-29
        相关资源
        最近更新 更多