import SwiftUI
extension Bundle {
func decode<T:Codable> (_ file:String) -> T {
guard let url = url(forResource: file, withExtension: nil) else {
fatalError("Failed to locate \(file) in bundle.")
}
guard let data = try? Data(contentsOf: url) else {
fatalError("Failed to load \(file) from bundle.")
}
let decoder = JSONDecoder()
let formatter = DateFormatter()
formatter.dateFormat = "y-MM-dd"
decoder.dateDecodingStrategy = .formatted(formatter)
guard let loaded = try? decoder.decode(T.self, from: data) else {
fatalError("Failed to decode \(file) from bundle.")
}
return loaded
}
}
struct Astronaut: Codable, Identifiable {
var id: String
var name:String
var description:String
}
struct Mission:Codable, Identifiable {
struct CrewRole:Codable {
let name:String
let role:String
}
let id:Int
let launchDate:Date?
let crew:[CrewRole]
let description:String
var displayName:String {
"Apollo \(id)"
}
var image:String {
"apollo\(id)"
}
var formattedLaunchDate:String {
if let launchDate = launchDate {
let formatter = DateFormatter()
formatter.dateStyle = .long
return formatter.string(from: launchDate)
} else {
return "N/A"
}
}
}
struct ContentView: View {
let astronauts:[Astronaut] = Bundle.main.decode("astronauts.json")
let missions:[Mission] = Bundle.main.decode("missions.json")
var body: some View {
NavigationView {
List(missions) { mission in
NavigationLink(destination: Text("Detail View")) {
Image(mission.image).resizable().scaledToFit().frame(width: 44, height: 44)
VStack(alignment: .leading){
Text(mission.displayName).font(.headline)
Text(mission.formattedLaunchDate)
}
}
}
.navigationBarTitle("Moonshot")
}
}
}
SwiftUI:extension & JSONDecoder &DateFormatter
最新推荐文章于 2024-05-22 11:34:03 发布