Ios 如何编写swift代码来显示Yelp星图?

Ios 如何编写swift代码来显示Yelp星图?,ios,enums,swifty-json,yelp,Ios,Enums,Swifty Json,Yelp,嘿,我正在尝试使用Yelp的Review API,但在构建/编写显示不同Yelp星级所需的代码时遇到了问题。我没有问题得到回应(成功了)。Yelp提供了他们所有不同星级(5、4.5、4等)的形象资产。因为评级响应是双精度的,所以我将其转换为字符串值。至于知道调用哪个,我创建了一个enum类,以便它知道使用哪个图像名称。使用这个名称,我就可以用它来找到我需要的图像资产 现在我这样构造代码,我的应用程序崩溃了。Xcode将构建它,但一旦打开应用程序,它就会崩溃 枚举类: import Foundat

嘿,我正在尝试使用Yelp的Review API,但在构建/编写显示不同Yelp星级所需的代码时遇到了问题。我没有问题得到回应(成功了)。Yelp提供了他们所有不同星级(5、4.5、4等)的形象资产。因为评级响应是双精度的,所以我将其转换为字符串值。至于知道调用哪个,我创建了一个enum类,以便它知道使用哪个图像名称。使用这个名称,我就可以用它来找到我需要的图像资产

现在我这样构造代码,我的应用程序崩溃了。Xcode将构建它,但一旦打开应用程序,它就会崩溃

枚举类:

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客户端服务类:

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视图中控制器:

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

}
生成时的错误是:致命错误:在展开可选值时意外发现nil

我不确定出了什么问题。我将评级实例化为评级类型是否正确?我应该把它挂起来吗


我知道这是很长的代码,但我希望有人能帮助!谢谢大家!

我确信它会崩溃。你写它的方式
let ratingDouble=review[“rating”]
。doubleValue您期望的是double。它将是0、4.5、3.0等,将被转换为字符串“0”、“4.5”、“3.0”等。然后您尝试使用
rating(rawValue:rating)
初始化评级,
rating
enum没有这些原始值作为“0”、“4.5”等,因此将返回nil。你是在用''强制展开它!“毫无疑问,它会崩溃。 您需要像这样设置枚举的格式

    enum Rating: String {

    case five = "5.0"
    case fourAndAHalf = "4.5"
    case four = "4.0"
    case threeAndAHalf = "3.5"
    case three = "3.0"
    case twoAndAHalf =  "2.5"
    case two = "2.0"
    case oneAndAHalf = "1.5"
    case one = "1.0"
    case zero = "0.0"

getImageName()-> String {
switch self {
case five:
    return "ImageNameForFive"
case fourAndHalf:
    return "ImageNameForFourAndHalf.
......

}
}

    }
改变

let rating = String(ratingDouble)


错误
致命错误:在展开可选值时意外发现nil。
在Swift无法执行操作时抛出,通常是在目标为
nil
为空、
不存在
未定义

如果某个值可能是
nil
空的
不存在的
未定义的
,则称为可选值。为了在代码中使用这些值,我们必须将其展开。如果该值是
nil
空的
不存在的
未定义的
,我们的应用程序将如果没有安全地打开包装,很可能会发生碰撞

为了在swift中安全地打开一个对象,我们可以使用
if let
guard statement
。只有当对象不为
null
时,代码才会写入其中

在swift中安全打开所有物体是一种良好的做法,以防止碰撞。下面是一个示例:

安全展开

// initalize a string that may be nil (an optional)
var string: String? = nil

// create a random number between 0-2
let randomNum:UInt32 = arc4random_uniform(3)

// create a switch to set the string value based on our number
switch (randomNum) {

case 0: 
   string = "Some String"

default:
  break

}

// attempt to print out our string

// using a guard statement
guard let string = string else {
   // handle if string is null
   return
}

// print the string from the guard
print(string)

// using if let
if let string = string {
   print(string)
} else {
  // handle string is null
}
不安全的拆封

// initalize a string that may be nil (an optional)
var string: String? = nil

// create a random number between 0-2
let randomNum:UInt32 = arc4random_uniform(3)

// create a switch to set the string value based on our number
switch (randomNum) {

case 0: 
   string = "Some String"

default:
  break

}

// attempt to print out our string

// using a guard statement
guard let string = string else {
   // handle if string is null
   return
}

// print the string from the guard
print(string)

// using if let
if let string = string {
   print(string)
} else {
  // handle string is null
}
//初始化可能为nil的字符串(可选) 变量字符串:字符串?=nil

// create a random number between 0-2
let randomNum:UInt32 = arc4random_uniform(3)

// create a switch to set the string value based on our number
switch (randomNum) {

case 0: 
   string = "Some String"

default:
  break

}

// attempt to print our string by forcefully unwrapping it even if it is null causing a crash if it is null
print(string!)
因此,您可以看到差异,在第二种情况下,如果随机数不是0,应用程序将崩溃,并出现与您相同的错误,因为它无法打开可选值

无需使用
if let
guard
即可安全地展开对象。这称为
内联条件
,它基本上是一个
if/else
子句,但速度更快

内联条件

// if the string is null, it will print the value beside the two `??`
print(string ?? "This is what is printed if the string is nil")
现在您已经掌握了所有这些知识,可以继续查看代码,看看是否强制展开了任何值。提示是您可以使用
来执行此操作

此外,即使是“0.5”之类的字符串,您创建的枚举也会采用“half”之类的字符串值而不是双精度值。所以它也可能崩溃

我挑选了一些可能导致崩溃的例子:

在reviewArray中查看
review[“rating”]。doubleValue
评级(原始值:评级)

timeCreated

引发异常的位置?因为我正在尝试填充imageView单元格(cell.yelpStars.image=UIImage(名为:review.rating.rawValue)),这是否意味着我必须更改资产名称?请参阅更新的答案。您可以获得类似cell.yelpStars.image=UIImage(名为:review.rating.getImagName)的图像