如何编写 swift 代码来显示 Yelp 星图?
How to write swift code to display Yelp Star Images?
嘿,我正在尝试使用 Yelp 的评论 API,但在 structuring/writing 显示不同 Yelp 星级评分所需的代码时遇到了问题。我没有问题得到响应(它是成功的)。 Yelp 提供了所有不同星级(5、4.5、4 等星级)的图像资产。因为评级响应是 Double,所以我将其转换为 String 值。至于知道调用哪个,我创建了一个枚举 class 以便它知道要使用哪个图像名称。使用该名称,我可以使用它来查找我需要的图像资产。
现在我以这种方式构建代码,我的应用程序崩溃了。 Xcode 将构建它,但在打开应用程序时,它会崩溃。
枚举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 客服 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 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 你期待双倍。它将是 0、4.5、3.0 等。这将转换为字符串“0”、“4.5”、“3.0” etc.Then 您尝试使用 Rating(rawValue : rating)
、Rating
枚举来初始化评级没有这些原始值如“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)
到
let rating = String.init(format: "%.1f", ratingDouble)
当 Swift 无法执行操作时,通常会在目标为 nil
、empty
、non-existent
或 [ 时抛出错误 fatal error: unexpectedly found nil while unwrapping an Optional value.
=17=]。
如果值可能是 nil
、empty
、non-existent
或 undefined
;它被称为可选值。为了在我们的代码中使用这些值,我们必须解包它们。如果该值为 nil
、empty
、non-existent
或 undefined
,如果未安全解包,我们的应用很可能会崩溃。
要在 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
}
不安全展开
// 初始化一个可能为 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
即可安全地展开对象。这被称为 inline conditional
,它基本上是一个 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")
现在您已经掌握了所有这些知识,您可以继续查看您的代码,看看您是否正在强行解包任何值。提示是您使用 !
来执行此操作。
此外,您制作的枚举采用 "half" 之类的字符串值,而不是双精度值,即使它是像“0.5”这样的字符串。所以它也可能崩溃
我挑选出的一些可能导致崩溃的例子是:
for review in reviewArray!
review["rating"].doubleValue
Rating(rawValue: rating)!
timeCreated!
嘿,我正在尝试使用 Yelp 的评论 API,但在 structuring/writing 显示不同 Yelp 星级评分所需的代码时遇到了问题。我没有问题得到响应(它是成功的)。 Yelp 提供了所有不同星级(5、4.5、4 等星级)的图像资产。因为评级响应是 Double,所以我将其转换为 String 值。至于知道调用哪个,我创建了一个枚举 class 以便它知道要使用哪个图像名称。使用该名称,我可以使用它来查找我需要的图像资产。
现在我以这种方式构建代码,我的应用程序崩溃了。 Xcode 将构建它,但在打开应用程序时,它会崩溃。
枚举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 客服 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 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 你期待双倍。它将是 0、4.5、3.0 等。这将转换为字符串“0”、“4.5”、“3.0” etc.Then 您尝试使用 Rating(rawValue : rating)
、Rating
枚举来初始化评级没有这些原始值如“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)
到
let rating = String.init(format: "%.1f", ratingDouble)
当 Swift 无法执行操作时,通常会在目标为 nil
、empty
、non-existent
或 [ 时抛出错误 fatal error: unexpectedly found nil while unwrapping an Optional value.
=17=]。
如果值可能是 nil
、empty
、non-existent
或 undefined
;它被称为可选值。为了在我们的代码中使用这些值,我们必须解包它们。如果该值为 nil
、empty
、non-existent
或 undefined
,如果未安全解包,我们的应用很可能会崩溃。
要在 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
}
不安全展开
// 初始化一个可能为 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
即可安全地展开对象。这被称为 inline conditional
,它基本上是一个 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")
现在您已经掌握了所有这些知识,您可以继续查看您的代码,看看您是否正在强行解包任何值。提示是您使用 !
来执行此操作。
此外,您制作的枚举采用 "half" 之类的字符串值,而不是双精度值,即使它是像“0.5”这样的字符串。所以它也可能崩溃
我挑选出的一些可能导致崩溃的例子是:
for review in reviewArray!
review["rating"].doubleValue
Rating(rawValue: rating)!
timeCreated!