天天看點

SwiftUI:extension & JSONDecoder &DateFormatter

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 &amp; JSONDecoder &amp;DateFormatter