如何在 SwiftUI 中显示 API 数据

问题描述

我正在为自己制作一个应用程序,它显示一个 subreddit 的评论提要,我试图展示用户的天赋。有两种方法可以显示 Reddit 的用户风格,一种是使用 author_flair_text 属性,该属性返回一个字符串,其中表情符号由其名称表示,例如 This is my flair :emoji:,另一种是使用 {{ 1}} 属性返回如下值:

author_flair_richtext

我正在 SwiftUI 中完成所有这些工作,这是我目前的代码

"author_flair_richtext": [
            {
              "a": ":emojiName:","e": "emoji","u": "link to the image for that emoji"
            },{
              "e": "text","t": " Flair text"
            }
          ]

然后我想做一些类似的事情,但这行不通,我不完全确定为什么,因为我是新手,但我最好的猜测是这不会与不透明的返回类型混淆有可选的视图。

struct FlairComponent: Decodable {
    var a: String?
    var e: String?
    var u: String?
    var t: String?
}

struct Comment: Decodable,Identifiable {
    //Other properties
    var author_flair_richtext: [FlairComponent?]
}

此外,非常感谢有关如何实现 getEmojiImage(for:) 函数的任何提示!请度过愉快的一天或一夜,感谢您阅读到这里:)

解决方法

如果我理解正确,在字段 e 中会出现不同的类型,如果这是一个 emoji,您需要获取它。这样对吗? 为此,最好创建一个单独的视图来执行此操作。让它是一个DisplayFlairView,其中会有一个变量richText - 是一个FlairComponent的数组。现在,在正文中,我们将检查是否有富文本,如果有,我们将创建一个带有组件的 HStack,检查它是文本还是表情符号。另外,为了获取图像,我推荐 URLImage - 一个非常好的库,非常适合一次缓存多个图像。示例代码

struct DisplayFlairView: View {
    
    let richText: [FlairComponent]?
    
    var body: some View {
        if let flairText = richText {
            HStack(spacing: 4) {
                ForEach(flairText,id: \.self) { oneFlair in
                    if oneFlair.e == "emoji" {
                        URLImage(url: oneFlair.u!) { image in
                            image
                                .resizable()
                                .aspectRatio(contentMode: .fit)
                        }
                    } else if oneFlair.e == "text" {
                        Text(oneFlair.t!)
                    }
                }
            }
        }
    }
}

并在您的评论中使用

struct CommentFeedView: View {
    @State var comments = [Comment]()
    var body: some View {
        ForEach(comments) { comment in
            if let flairComponents = comment.author_flair_richtext,!flairComponents.isEmpty {
                 DisplayFlairView(richText: flairComponents)
            }
        }
    }
}