Module 2 Lesson 9 iOS Networking

Hi there!

I have a question regarding ratings we get back from the YELP API. In the documentation I can see that the API should return double with 0.5 increments. (0.0, 0.5, 1.0…) However, I can see in my response in the ProxyMan is completely different. I am getting ratings like 3.3, 3.7, 4.9 and so on.

This creates an issue with our image assets as we only have image assets for 0.5 increments, so I was just wondering if anyone else had this issue and what was your solution?

I’ll share mine. In Helpers folder, I have created a new ImageHelper struct where I created a static method called imageRating. It takes in rating as Double and returns Double. The double that it returns is calculated as follows: return (rating * 2).rounded() / 2

Let me know if you came up with a better solution :slight_smile:

Peter

I just ran into this myself because I was wondering why no ratings were showing up in my simulator… my solution is pretty much the same as yours, except I don’t use a helper method but a computed property instead. The relevant part of my business struct then looks like this:

...
var isClosed: Bool?
    var url: String?
    var reviewCount: Int?
    var categories: [Category]
    var rating: Double? { // Computed property to adjust rating
        get {
            guard let rawRating = _rating else { return nil }
            return (rawRating * 2).rounded() / 2
        }
        set {
            _rating = newValue
        }
    }
    var coordinates: Coordinate?
    var transactions: [String]?
    var price: String?
    var location: Location?
...

I got a bit ahead of myself with autocomplete (https://codeium.com/) in Xcode, which suggested the Business struct to conform to the Codable protocol instead of Decodable like Chris does in the video.

Encodable becomes relevant when you want to send data back to the API, which of course we’re not doing yet at this point in the course.

I’ll leave it to my good friend gpt-4 to explain the rest so you hopefully get a comprehensive answer:

Codable vs. Decodable

  • Decodable: This is a protocol in Swift that allows your struct or class to parse data from a format like JSON. If you’re only fetching data from an API and not sending data back, Decodable is what you need.
  • Codable: This is actually a type alias that combines two protocols: Decodable and Encodable. It’s used when you both fetch data from an API (decode) and send data back (encode). Since you’re planning ahead to also send data back to the API, using Codable is a proactive choice.

Computed Properties

A computed property calculates a value instead of storing it. Think of it as a special kind of property that runs a piece of code to get its value. In your Business struct, you want the rating to always be in 0.5 steps. Instead of storing this adjusted rating directly, you compute it on-the-fly whenever it’s accessed.

Why the _rating and Additional Entry in CodingKeys

  • _rating: This is a convention where an underscore (_) is used to name a property that’s meant for “private” use within your struct or class. It’s like saying, “This is just for us inside the code, not for others to use directly.” You’re using _rating to hold the original rating value from the API.
  • Computed Property for rating: You then have a computed property rating that looks at _rating, does some math to adjust it to the nearest 0.5 step, and presents this adjusted value whenever rating is accessed.
  • CodingKeys: This is a special enum that tells Swift how to map JSON keys to your struct’s properties when decoding (and encoding). Since you’re using _rating to store the original rating value and rating as a computed property (which doesn’t directly correspond to a JSON key because it’s computed, not stored), you need to tell Swift: “Hey, when you see ‘rating’ in the JSON, please save that value in _rating for me.” That’s why you add an entry for _rating in CodingKeys, mapping it to the JSON key "rating".

Summary

By using Codable, you’re preparing to both fetch and send data. The _rating property holds the original rating value from the API, and it’s marked with an underscore to indicate it’s meant for internal use. The rating computed property then provides a rounded value in 0.5 steps whenever it’s accessed, ensuring consistency in how ratings are presented in your app. The CodingKeys enum is necessary to map the JSON rating key to your _rating property, enabling the correct decoding (and later encoding) of your data.

I hope that wasn’t overwhelming as that wasn’t my intention. Your solution is perfectly fine and it’s great you came up with it yourself! :slight_smile:

I tend to get a bit ahead of myself but I’m learning all this stuff all the same so there ya go :smiley:

1 Like

If anyone comes across this later… I recommend you solve this the way the OP did. My solution required even more edits to Business.swift than what I mentioned in my last post.

Specifically, using a computed property and conforming to the Codable protocol “broke” my Business.swift model. I had to add a custom initializer method as well as an “encode” function to make it work.

Though what I did is what you might end up needing when decoding AND encoding when working with an API, it’s unnecessarily complicated for this stage in the course.

Keep it simple :slight_smile:

1 Like