(3) Errors when calling data from API using Contentful & SwiftUI

176 views Asked by At

Forgive me as I am extremely novice with SwiftUI... I am attempting to pull data from the CMS and put it in my app however it is throwing three errors on each attempt for the data to be retrieved and placed...

The errors are highlighting in the sections that read "api.beers.title", "api.beers.type" and "api.beers.description".

Errors

  • Value of type 'API' has no dynamic member 'beers' using key path from root type 'API'
  • Referencing subscript 'subscript(dynamicMember:)' requires wrapper 'ObservedObject.Wrapper'
  • Initializer 'init(_:)' requires that 'Binding' conform to 'StringProtocol'

API Call Code

func getArray(id: String, completion: @escaping([Entry]) -> ()) {
    let query = Query.where(contentTypeId: id)

    client.fetchArray(of: Entry.self, matching: query) { result in
        switch result {
        case .success(let array):
            DispatchQueue.main.async {
               completion(array.items)
            }
        case .failure(let error):
            print(error)
        }
    }
}

class API: ObservableObject {
    @Published var draft: [Draft] = draftData

    init() {
        getArray(id: "beers") { (items) in
            items.forEach { (item) in
                self.draft.append(Draft(
                    title: item.fields["title"] as! String,
                    type: item.fields["type"] as! String,
                    description: item.fields["type"] as! String
                ))
            }
        }
    }
}
struct LandingPageView: View {
        var body: some View {
            VStack {
                VStack {
                    Text("Problem Solved")
                    Text("Brewing Company")
                }
                .font(.system(size: 24, weight: .bold))
                .multilineTextAlignment(.center)
                .foregroundColor(Color("TextColor"))

                VStack {
                    Text("NEWS & EVENTS")
                        .font(.title)
                        .fontWeight(.bold)
                        .padding(.top, 40)
                        .foregroundColor(Color("TextColor"))

                    NewsTile()
                    
                    Text("On Draft" .uppercased())
                        .font(.title)
                        .fontWeight(.bold)
                        .padding(.top)
                        .foregroundColor(Color("TextColor"))

                    ScrollView(.horizontal, showsIndicators: false) {
                        HStack(spacing: 20) {
                            ForEach(draftData) { item in
                                GeometryReader { geometry in
                                    DraftList(beer: item)
                                        .rotation3DEffect(Angle(degrees: Double(geometry.frame(in: .global).minX - 30) / -20), axis: (x: 0, y: 10.0, z: 0))
                                }
                                .frame(width: 275, height: 200)
                                
                            }
                        }
                    .padding(.leading, 30)
                    .padding(.trailing, 30)
                }
            }
            .frame(width: 400, height: 850)
            .background(Color("PageBackground"))
            .edgesIgnoringSafeArea(.all)
            
        }
    }
}


struct DraftList: View {
    var width: CGFloat = 275
    var height: CGFloat = 200
    
    @ObservedObject var api = API()
    var beer: Draft
    
    var body: some View {
        VStack {
            Spacer()
            Text(api.beers.title)
                .font(.system(size: 24, weight: .bold))
                .padding(.horizontal, 20)
                .frame(width: 275, alignment: .leading)
                .foregroundColor(Color("TextColor"))
            
            Text(api.beers.type .uppercased())
                 .font(.system(size: 14, weight: .bold))
                 .frame(maxWidth: .infinity, alignment: .leading)
                 .padding(.horizontal, 20)
            
            Text(api.beers.description)
                .font(.system(size: 12))
                .padding(.horizontal, 20)
                .padding(.top, 10)
            Spacer()
            HStack {
//                Add OnTapGesture to bring to full view + cart options.
                Text("Click To Add To Cart")
                    .font(.footnote)
                Image(systemName: "cart")

            }
            .padding(.bottom)

            
        }
        .padding(.horizontal, 20)
        .frame(width: width, height: height)
        .background(Color("TileOrangeColor"))
        .cornerRadius(15)
        .shadow(color: Color.black.opacity(0.2), radius: 5, x: 0, y: 5)

        
    }
}

1

There are 1 answers

5
Ernist Isabekov On BEST ANSWER
  1. Your draft is array, you can access by index like Text(api.draft[0].title)
  2. @Published var draft: [Draft] = draftData instead @Published var draft: [Draft] = []

Updated:

class API: ObservableObject {
    @Published var draft: [Draft] = [] 

    init() {
        getArray(id: "beers") { (items) in
            items.forEach { (item) in
                self.draft.append(Draft(
                    title: item.fields["title"] as! String,
                    type: item.fields["type"] as! String,
                    description: item.fields["type"] as! String
                ))
            }
        }
    }
}

struct DraftList: View {
    var width: CGFloat = 275
    var height: CGFloat = 200
    @ObservedObject var api = API()
    var body: some View {
            VStack {
             ForEach(api.draft) {item in 
                Spacer()
                Text(item.title)
                    .font(.system(size: 24, weight: .bold))
                    .padding(.horizontal, 20)
                    .frame(width: 275, alignment: .leading)
                    .foregroundColor(Color("TextColor"))
    
                ...
             }
            }
            .padding(.horizontal, 20)
            .frame(width: width, height: height)
            .background(Color("TileOrangeColor"))
            .cornerRadius(15)
            .shadow(color: Color.black.opacity(0.2), radius: 5, x: 0, y: 5)
        }
    }