Day 99 of #100DaysOfSwiftUI

Start 100DaysOfSwiftUI from 2020.Mar.18th.

Day 99: Project 19, part four
done with 3 hours

For 1st challenge,

in ResortView.swift

ZStack(alignment: .bottomTrailing) {  // <- new
    Image(decorative: resort.id)
    .resizable()
    .scaledToFit()
    Text(resort.imageCredit)         // <- new
        .font(.footnote)             // <- new
}                                    // <- new

for 2nd challenge

for load

init() {
    // load our saved data
    if let data = UserDefaults.standard.data(forKey: saveKey), let decodedData = try? JSONDecoder().decode(Set.self, from: data) {
        resorts = decodedData
    } else {
        self.resorts = []
    }
}
for save

func save() {
    // write out our data
    let data = try? JSONEncoder().encode(resorts)
    if let encodedData = data {
        UserDefaults.standard.set(encodedData, forKey: saveKey)
    }
}

for 3rd challenge:
On top of 3rd challenge, I added how many resorts are there for each condition. Ex: how many resorts are there for size small.

create ResortList class

ResortList.swft

class ResortList: ObservableObject {
    var resorts:[Resort]
    @Published var sortName:String = "name"
    @Published var countryFileter: String = ""
    @Published var sizeFilter: Int = 0
    @Published var priceFilter: Int = 0
    
    init() {
        resorts = []
    }
    
    init(fromBundle name:String) {
        resorts = Bundle.main.decode("resorts.json")
    }

    func sortedList(sortType:String) -> [Resort] {
        switch sortName {
        case "name":
            return resorts.sorted(by: {$0.name < $1.name})
        case "country":
            return resorts.sorted(by: {$0.country < $1.country})
        default:
            return resorts
        }
    }
    
    func filterWithCondition( resorts: [Resort]) -> [Resort] {
        return resorts.filter({ self.countryFileter == "" || self.countryFileter == $0.country}).filter({self.sizeFilter==0 || self.sizeFilter == $0.size}).filter({self.priceFilter==0 || self.priceFilter == $0.price} )
    }
    
    func processedList() -> [Resort] {
        return filterWithCondition(resorts: sortedList(sortType: sortName))
    }
    
    var countries:[String] {
        return Array(Set(resorts.map({$0.country}))).sorted()
    }

    var prices:[Int] {
        return [1,2,3]
    }
    
    var sizes:[Int] {
        return [1,2,3]
    }
    
    func sizeStringWithNum(size:Int) -> String {
        switch size {
        case 1:
            return "Small"+"(\(resorts.filter({$0.size == size}).count))"
        case 2:
            return "Average"+"(\(resorts.filter({$0.size == size}).count))"
        default:
            return "Large"+"(\(resorts.filter({$0.size == size}).count))"
        }
    }

    func priceStringWithNum(price:Int) -> String {
        String(repeating: "$", count: price)+"(\(resorts.filter({$0.price == price}).count))"
    }
}

Add code to ContentView

コード

struct ContentView: View {
    @ObservedObject var favorites = Favorites()
    @ObservedObject var resorts = ResortList(fromBundle: "resorts.json")
    @State private var isShowingSortFilter = false

    var body: some View {
        NavigationView {
            List(resorts.processedList()) { resort in
                NavigationLink(destination: ResortView(resort: resort)) {
                    Image(resort.country)
                        .resizable()
                        .scaledToFill()
                        .frame(width: 40, height: 25)
                        .clipShape(
                            RoundedRectangle(cornerRadius: 5)
                        )
                        .overlay(
                            RoundedRectangle(cornerRadius: 5)
                                .stroke(Color.black, lineWidth: 1)
                        )
                    VStack(alignment: .leading) {
                        Text(resort.name)
                            .font(.headline)
                        Text("\(resort.runs) runs")
                            .foregroundColor(.secondary)
                    }.layoutPriority(1)
                    if self.favorites.contains(resort) {
                        Spacer()
                        Image(systemName: "heart.fill")
                        .accessibility(label: Text("This is a favorite resort"))
                            .foregroundColor(.red)
                    }
                }
            }
            .navigationBarTitle("Resorts")
            .navigationBarItems(trailing: Button("sort/filter"){
                self.isShowingSortFilter.toggle()
            })
            
            WelcomeView()
        }
        .environmentObject(favorites)
        .sheet(isPresented: $isShowingSortFilter) {
            VStack {
                Text("Sort")
                    .font(.headline)
                Picker(selection: self.$resorts.sortName, label: Text("Sort")) {
                    Text("name").tag("name")
                    Text("country").tag("country")
                }
                .font(.footnote)
                .pickerStyle(SegmentedPickerStyle())

                Text("Filter")
                    .font(.headline)
                Text("Country")
                    .font(.subheadline)
                Picker(selection: self.$resorts.countryFileter, label: Text("country"), content: {
                    Text("-").tag("")
                    ForEach(self.resorts.countries, id: \.self) { name in
                        Text(name)
                    }
                })
                .font(.footnote)
                .pickerStyle(SegmentedPickerStyle())

                Text("Size")
                    .font(.subheadline)
                Picker(selection: self.$resorts.sizeFilter, label: Text("size"), content: {
                    Text("-").tag(0)
                    ForEach(self.resorts.sizes, id: \.self) { size in
                        Text(self.resorts.sizeStringWithNum(size: size))
                        .tag(size)
                    }
                })
                .font(.footnote)
                .pickerStyle(SegmentedPickerStyle())

                Text("Price")
                    .font(.subheadline)
                Picker(selection: self.$resorts.priceFilter, label: Text("price"), content: {
                    Text("-").tag(0)
                    ForEach(self.resorts.prices, id: \.self) { price in
                        Text(self.resorts.priceStringWithNum(price: price))
                        .tag(price)
                    }
                })
                .font(.footnote)
                .pickerStyle(SegmentedPickerStyle())
                Button("done"){
                    self.isShowingSortFilter.toggle()
                }
            }
        }
    }
}

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です