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; DR
새 빈 파일을 프로젝트에 추가하고 이름을 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를 가리 킵니다. ID가 자동으로 초기화되기 때문에 json 파일에 unqiue ID를 제공 할 필요가 없습니다. 그러나 컴파일러 경고를 방지하려면 코딩 키를 제공해야합니다 ( 여기 참조 ).