0

Allo, Hi, im new with SwiftUI and im facing some issue with the Yelp API and can't find answer anywhere... I'm creating a restaurant app and I want to add a on the business detail page a list of Yelp transactions that the business is registered for ("pickup", "delivery", and "restaurant_reservation").

I've try a lot of way to retrieved it but im about to give up... I don't know if it's me who's dumb or anything but my brain can't figured it out anymore. I've tried to get the data with "ForEach" and all any other way we usually get array data...

Second question (similar as the previous one) how can I retrieve the category alias/title from the API? I want to be able to filter the business based on their categories and also show on the business detail page the category associated to it.

Thank you :)

Yelp Response Body Example :

   {
  "total": 144,
  "businesses": [
    {
      "id": "gR9DTbKCvezQlqvD7_FzPw",
      "alias": "north-india-restaurant-san-francisco",
      "price": "$$",
      "url": "https://www.yelp.com/biz/north-india-restaurant-san-francisco",
      "rating": 4,
      "location": {
        "zip_code": "94105",
        "state": "CA",
        "country": "US",
        "city": "San Francisco",
        "address2": "",
        "address3": "",
        "address1": "123 Second St"
      },
      "categories": [
        {
          "alias": "indpak",
          "title": "Indian"
        }
      ],
      "phone": "+14153481234",
      "coordinates": {
        "longitude": -122.399305736113,
        "latitude": 37.787789124691
      },
      "image_url": "http://s3-media4.fl.yelpcdn.com/bphoto/howYvOKNPXU9A5KUahEXLA/o.jpg",
      "is_closed": false,
      "name": "North India Restaurant",
      "review_count": 615,
      "transactions": ["pickup", "restaurant_reservation"]
    },
    // ...
  ]
}

Here is my Business model :

class Business: Decodable, Identifiable, ObservableObject {
    
    @Published var imageData: Data?
    
    var id: String?
    var alias: String?
    var name: String?
    var imageUrl: String?
    var isClosed: Bool?
    var url: String?
    var reviewCount: Int?
    var categories: [Category]?
    var rating: Double?
    var coordinates: Coordinate?
    var transactions: [String]?
    var price: String?
    var location: Location?
    var phone: String?
    var displayPhone: String?
    var distance: Double?
    
    enum CodingKeys: String, CodingKey {
        
        case imageUrl = "image_url"
        case isClosed = "is_closed"
        case reviewCount = "review_count"
        case displayPhone = "display_phone"
        
        case id
        case alias
        case name
        case url
        case categories
        case rating
        case coordinates
        case transactions
        case price
        case location
        case phone
        case distance
    }
    
    func getImageData() {
        
        // Check that image url isn't nil
        guard imageUrl != nil else {
            return
        }
        
        // Download the data for the image
        if let url = URL(string: imageUrl!) {
            
            // Get a session
            let session = URLSession.shared
            let dataTask = session.dataTask(with: url) { (data, response, error) in
                
                if error == nil {
                    
                    DispatchQueue.main.async {
                        // Set the image data
                        self.imageData = data!
                    }
                }
            }
            dataTask.resume()
        }
    }
    
    static func getTestData() -> Business {
        let b = Business()
        return b
    }
}
struct Category: Decodable {
    var alias: String?
    var title: String?
}

Here an example of my code :

struct BusinessDetail: View {
    
    var business: Business

    
    @State private var showDirections = false
    
    var body: some View {
        
        VStack (alignment: .leading) {
            
            VStack (alignment:.leading, spacing:0) {
                
                GeometryReader() { geometry in
                    
                    // Business image
                    let uiImage = UIImage(data: business.imageData ?? Data())
                    Image(uiImage: uiImage ?? UIImage())
                        .resizable()
                        .scaledToFill()
                        .frame(width: geometry.size.width, height: geometry.size.height)
                        .clipped()
                        
                }
                .ignoresSafeArea(.all, edges: .top)
                
                
                // Open / closed indicator
                ZStack (alignment: .leading) {
                    Rectangle()
                        .frame(height: 35)
                        .foregroundColor(business.isClosed! ? Color("icon-primary") : Color("background"))
                    
                    Text(business.isClosed! ? "Closed" : "Open")
                        .foregroundColor(.white)
                        .font(.textHeader)
                        .padding(.leading)
                }
            }
            
            
            
            Group {
                
                HStack {
                    BusinessTitle(business: business)
                        .padding()
                    Spacer()
                }
  
                
                // Phone
                HStack {
                    Text("Phone:")
                        .bold()
                    Text(business.displayPhone ?? "")
                    Spacer()
                    Link("Call", destination: URL(string: "tel:\(business.phone ?? "")")!)
                }
                .padding()
                
                // Transactions
           if business.transactions != nil {

                ForEach(business.transactions!, id: \.self) { transaction in
            Text(transaction)
                        .font(.bodyParagraph)
                }
            }
mry15
  • 1
  • 2
  • 1
    Can you describe how the result you're getting is differing from what you expect? It's not quite clear from your question what/where the problem is. For example, it could be a parsing issue, but you don't show any of that code. Also, you haven't included all of the necessary types (such as `Location`, which it looks like is central to the issue). Can you include a [mre]? Finally, you may want to read about `if let` "Optional binding" -- force unwrapping with `!` is dangerous and can lead to crashes. – jnpdx Jan 15 '22 at 02:35
  • One question at a time, s'il vous plait... –  Jan 15 '22 at 02:38
  • @jnpdx Well, the thing is that both of the question are kinda the same thing... I wan't to get the detail in the bracket [] ... but when I write something like `Text(business.transactions)` it gives me an error "No exact matches in call to initializer" or when I try something similar for the categories `Text(business.categories.title)` it gives me also an error "Value of type '[Category]?' has no member 'title'". I don't really know how to be more clear... I'm able to parse any other data but these two... no clue! – mry15 Jan 15 '22 at 02:46
  • `categories` is an Array, so you can't access `title` on it without choosing (or looping through) an element. Same issue with `transactions`. Your code for `ForEach` for the transactions looks okay (with the exception of the force unwrap I mentioned), but it's not clear from what you've written how it differs from what you expect (and no one can test your code without a [mre]) – jnpdx Jan 15 '22 at 02:51
  • @LaBanana je vais essayer next time! But as mention on my previous comment... kinda feel its almost the same issue with bot variable... one have a key:String tho and the other is an array list if im not wrong... but both are array that I've NO CLUE how to retrieved them from the API. I get that it might be empty but if not, I wanna display it! It's late, maybe i'm not as clear as I thing I am haha – mry15 Jan 15 '22 at 02:57

0 Answers0