Hey I'm trying to use Yelp's Review API and am having trouble structuring/writing the code necessary to display the different Yelp Star Ratings. I have no problem getting the response (it's successful). Yelp has provided image assets of all their different star ratings (5, 4.5, 4 etc. stars). Because the rating response is as a Double, I converted that into a String value. As for knowing which to call, I created an enum class so that it knows which image name to use. Using that name, I can then use it to find the image asset I need.
Now that I structure the code this way, my app crashes. Xcode will build it but upon opening the app, it crashes.
Enum class:
import Foundation
import UIKit
enum Rating: String {
case five = "regular_5"
case fourAndAHalf = "regular_4_half"
case four = "regular_4"
case threeAndAHalf = "regular_3_half"
case three = "regular_3"
case twoAndAHalf = "regular_2_half"
case two = "regular_2"
case oneAndAHalf = "regular_1_half"
case one = "regular_1"
case zero = "regular_0"
}
Yelp Client Service class:
import Foundation
import Alamofire
import SwiftyJSON
class YelpClientService {
static func getReviews(url: String, completionHandler: @escaping ([Review]?)-> Void)
{
let httpHeaders: HTTPHeaders = ["Authorization": "Bearer \(UserDefaults.standard.string(forKey: "token") ?? "")"]
//removing diacritics from the URL
if let requestUrl = URL(string: url.folding(options: .diacriticInsensitive, locale: .current))
{
Alamofire.request(requestUrl, encoding: URLEncoding.default, headers: httpHeaders).responseJSON { (returnedResponse) in
let returnedJson = JSON(with: returnedResponse.data as Any)
let reviewArray = returnedJson["reviews"].array
print(reviewArray as Any)
var reviews = [Review]()
for review in reviewArray! {
let userName = review["user"]["name"].stringValue
let ratingDouble = review["rating"].doubleValue
let rating = String(ratingDouble)
let text = review["text"].stringValue
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let timeCreated = formatter.date(from: review["time_created"].stringValue)
let url = review["url"].stringValue
let review = Review(rating: Rating(rawValue: rating)!, userName: userName, text: text, timeCreated: timeCreated!, url: url)
reviews.append(review)
}
completionHandler(reviews)
}
}
else
{
print("invalid url")
completionHandler(nil)
}
}
}
Func in View Controller thats displaying the Star:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "reviewCell", for: indexPath) as! ReviewCell
let review = reviewList[indexPath.row]
print(review.userName)
cell.userName.text = review.userName
cell.reviewText.text = review.text
cell.yelpStars.image = UIImage(named: review.rating.rawValue)
//cell.date.text = review.timeCreated
return cell
}
The error when I build is: fatal error: unexpectedly found nil while unwrapping an Optional value.
I'm not sure what went wrong. Is it correct of me to instantiate rating as a Rating type? Should I keep it String?
I realize this is long code but I hope someone can help! Thank you!