Interface utilisateur Swift: comment créer un fichier JSON au lieu d'appeler l'image en mode grille?
Je crée une application de fond d'écran et l'une des vues est une vue en grille pour ajouter des photos comme vous pouvez le voir ici: la vue en grille avec les images
J'ai ajouté des images à la grille elle-même, mais j'ai remarqué qu'elles avaient des espaces et je dois les regrouper pour pouvoir ajouter comme 50 images dans la vue de la grille, mais il m'est venu à l'esprit de créer un fichier JSON dans la vue de la grille et de le laisser lire il avec toutes les photos, mais je ne sais pas comment créer le JSON et le connecter à la vue en grille
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)
}
}
Réponses
TL; DR
Ajoutez un nouveau fichier vide à votre projet et appelez-le ImageList.json
. Collez les données suivantes dans le fichier 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
}
]
Utilisez l'exemple de travail suivant ci-dessous:
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()
}
}
Explication détaillée
Le fichier json créé fait partie de votre bundle. Pour accéder à ce fichier, vous pouvez créer une URL pointant vers lui avec:
Bundle.main.url(forResource: "ImageList", withExtension: "json")
Maintenant, créez une tâche qui s'exécute de manière asynchrone en arrière-plan avec
DispatchQueue.global(qos: .background).async { }
Dans cette tâche, décodez les données brutes du fichier json dans un tableau de la structure ImageSpecification
. Cette structure décrit à quoi ressemble un élément unique. En le rendant conforme au protocole, Codable
vous pouvez utiliser le JSONDecoder
.
Toute mise à jour à l'écran doit être effectuée sur le fil principal. C'est pourquoi vous devez vous assurer de pousser les nouveaux éléments dans votre stockage sur le thread principal en utilisant une nouvelle file d'attente:
DispatchQueue.main.async { }
Dans votre vue, vous pouvez désormais utiliser votre DataModel
classe, qui charge les données lors de l'initialisation. À l'intérieur de LazyVGrid
, une ForEach
vue est utilisée pour parcourir les données. Puisque ForEach
attend un identifiant hachable, rendez la structure complète conforme au Hashable
protocole ou pointez sur l'identifiant unique. Il n'est pas nécessaire de fournir un identifiant unqiue dans le fichier json, car l'identifiant est automatiquement initialisé. Vous devez cependant fournir les clés de codage pour éviter les avertissements du compilateur (voir ici ).