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