每次我尝试访问它时,UUID 类型的结构 ID 都会更改

Struct's id of type UUID changes everytime i try to access it

我有一个从 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 结构创建 ID 以便它不会每次都重新生成?

您的扩展程序中的 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。

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

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

您还需要手动声明一个 CodingKey 符合 enum 并从其案例中省略 id 键,以告诉编译器 id 不应从中解码JSON.

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)
    }
}

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

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

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

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


但是如果您不能编辑此结构(这可能是您使用扩展的原因),您可以执行以下操作:使用 Hashable 扩展您的结构,然后您可以访问对象 hashValue 是基于所有属性计算的,所以只有在所有属性中具有相同值的两个对象,这个值才会相同,这通常适合唯一标识符

extension Article: Hashable {
    
}

用法

Text("\(article.hashValue)")