arrays - Swift UI:如何创建 json 文件而不是在网格视图中调用图像?
问题描述
我正在创建一个壁纸应用程序,其中一个视图是用于添加图片的网格视图,如您在此处看到的:带有图像的网格视图
我将图像添加到网格本身,但我注意到它们有空格,我必须对它们进行分组,这样我才能在网格视图中添加 50 个图像,但我想到要为网格视图创建一个 JSON 文件并让它读取它包含所有图片,但我不知道如何创建 JSON 并将其连接到网格视图
struct GridContentView: View {
var items = Item.stubs
let data = (1...1000).map { "Item \($0)" }
let columns = [
GridItem(.adaptive(minimum: 80)),
GridItem(.adaptive(minimum: 80)),
GridItem(.adaptive(minimum: 80))
]
let rows = [
GridItem(.adaptive(minimum: 80)),
GridItem(.adaptive(minimum: 80)),
GridItem(.adaptive(minimum: 80))
]
var body: some View {
ScrollView {
Section{
LazyVGrid(columns: columns, spacing: 30) {
// adding images
Image("joker1")
.resizable()
.frame(width: 100, height: 200)
Image("joker2")
.resizable()
.frame(width: 100, height: 200)
Image("joker3")
.resizable()
.frame(width: 100, height: 200)
Image("joker4")
.resizable()
.frame(width: 100, height: 200)
Image("joker5")
.resizable()
.frame(width: 100, height: 200)
Image("joker6")
.resizable()
.frame(width: 100, height: 200)
Image("joker7")
.resizable()
.frame(width: 100, height: 200)
Image("joker8")
.resizable()
.frame(width: 100, height: 200)
Image("joker9")
.resizable()
.frame(width: 100, height: 200)
Image("joker10")
.resizable()
.frame(width: 100, height: 200)
}
}
解决方案
TL; 博士
将一个新的空文件添加到您的项目并调用它ImageList.json
。将以下数据粘贴到 json 文件中:
[
{
"name": "image1",
"width": 100.0,
"height": 200.0
},
{
"name": "image2",
"width": 100.0,
"height": 200.0
},
{
"name": "image3",
"width": 100.0,
"height": 200.0
}
]
使用以下工作示例:
import SwiftUI
struct ImageSpecification: Codable {
let id = UUID()
let name: String
let width: CGFloat
let height: CGFloat
private enum CodingKeys: CodingKey {
case name
case width
case height
}
}
class DataModel: ObservableObject {
@Published var images: [ImageSpecification] = []
init() {
DispatchQueue.global(qos: .background).async {
if let jsonURL = Bundle.main.url(forResource: "ImageList", withExtension: "json") {
let jsonData = try! Data(contentsOf: jsonURL)
let jsonDecoder = JSONDecoder()
let objects = try! jsonDecoder.decode([ImageSpecification].self, from: jsonData)
DispatchQueue.main.async {
self.images.append(contentsOf: objects)
}
}
}
}
}
struct ContentView: View {
@StateObject var model = DataModel()
let columns = [
GridItem(.adaptive(minimum: 80)),
GridItem(.adaptive(minimum: 80)),
GridItem(.adaptive(minimum: 80))
]
var body: some View {
ScrollView {
LazyVGrid(columns: columns, spacing: 30) {
ForEach(self.model.images, id:\.self.id) { item in
Image(item.name)
.resizable()
.frame(width: item.width, height: item.height)
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
详细解释
创建的 json 文件是捆绑包的一部分。要访问此文件,您可以创建一个指向它的 URL:
Bundle.main.url(forResource: "ImageList", withExtension: "json")
现在,创建一个在后台异步运行的任务
DispatchQueue.global(qos: .background).async { }
在此任务中,将 json 文件的原始数据解码为 struct 的数组ImageSpecification
。该结构描述了单个项目的外观。通过使其符合协议Codable
,您可以使用JSONDecoder
.
屏幕上的任何更新都必须在主线程上完成。这就是为什么您必须确保通过使用新队列将新项目推送到主线程上的存储中:
DispatchQueue.main.async { }
在您的视图中,您现在可以使用您的DataModel
类,该类在初始化时加载数据。在内部LazyVGrid
,ForEach
视图用于循环数据。由于ForEach
需要一个可散列的 id,要么使完整的结构符合Hashable
协议,要么指向唯一的 id。不需要在 json 文件中提供 unqiue id,因为 id 会自动初始化。但是,您必须提供编码密钥以防止编译器警告(请参阅此处)。
推荐阅读
- javascript - Handlebars sanitize string - SyntaxError: unterminated string literal
- java - 如何在java中拆分数字文件?
- maven - maven能否提前检测出依赖冲突导致的runtime NoSuchMethodError?
- javascript - 你能检测出用户是否处于 Chrome 的访客模式吗?
- jira - JIRA:您如何围绕自定义字段创建自定义逻辑?
- python-3.x - SpaCy 中的非名词短语分块
- javascript - 如何从 SVGJS 3 中的外部文件加载 SVG?
- javascript - 替换jQuery中特定类的图像标题属性
- c# - 将图像添加到资源文件中
- python - 计算文本文件中每个单词的频率,使用 python 将其存储在变量中