我在故事板和连接的网点中拍摄了 5 个图像视图
@IBOutlet var starRatingImageViews: [UIImageView]!
我正在从 json 中获取字符串值以获得 rating 像这样
rating = "4.2"
例如。
rating = "4.2" i need to show 4 full stars and one half star
但显示不正确
o/p:这里我有“4.2”评级,但它的星星在输出中显示错误。请指导我解决这个问题
代码: 这里
user.rating = "4.2"
但在 o/p 中显示错误的星星。 fillStars
方法我哪里错了。请指导。
@IBOutlet var starRatingImageViews: [UIImageView]!
if let rating = Float(user.rating ?? "0.0") {
rating.fillStars(in: starRatingImageViews)
}
func fillStars(in imageViews: [UIImageView], withEmptyStar color: UIColor = .darkGray) {
for i in (0 ..< imageViews.count) {
imageViews[i].contentMode = .scaleAspectFit
let review = Int(Float(self))
if (i < review) {
imageViews[i].image = UIImage(systemName: "star.fill")?.withRenderingMode(.alwaysOriginal).withTintColor(CommonColor.yellowColor)
} else {
if (self - Float(review)) > (0.5), i == review {
imageViews[i].image = UIImage(systemName: "star.fill")?.withRenderingMode(.alwaysOriginal).withTintColor(CommonColor.yellowColor)
} else if (self - Float(review)) <= (0.5), (self - Float(review)) > (0.0), i == review {
imageViews[i].image = UIImage(systemName: "star.leadinghalf.fill")?.withRenderingMode(.alwaysOriginal).withTintColor(CommonColor.yellowColor)
} else {
imageViews[i].image = UIImage(systemName: "star")?.withRenderingMode(.alwaysOriginal).withTintColor(color)
}
}
}
}
问题是您正在使用
self - Float(review)
来确定要绘制哪种星星,但是 self
独立于您的循环,并且您甚至不一致,因为您使用 i < review
作为第一次测试。你可以做到这一点,但它比需要的更难。如果情况比您需要的多,事情就会变得更加混乱:您需要画一颗实心星、半实心星或空心星。那是 3 个案例,但你的代码中有 4 个,因为你复制了完整的星号案例。
当我遇到这样的问题时,我更愿意考虑计算需要绘制的当前指标(星号,在你的情况下)的百分比,然后使用该结果来决定做什么,而不是混合一起计算和决策。所以我会修改你的代码是这样的:
func clamp<T: Comparable>(_ value: T, to range: ClosedRange<T>) -> T {
return max(range.lowerBound, min(range.upperBound, value))
}
func fillStars(
in imageViews: [UIImageView],
withEmptyStar color: UIColor = .darkGray)
{
let review = Float(self) // Is this needed now?
for i in imageViews.indices
{
imageViews[i].contentMode = .scaleAspectFit
let tintColor: UIColor
let starName: String
// Calculate the percentage of the current star to draw
let percentOfThisStar = clamp(review - Float(i), to: 0...1)
// Now use the percentage to pick the image/tinting
if percentOfThisStar == 0
{ // Empty star
tintColor = color
starName = "star"
}
else
{
tintColor = CommonColor.yellowColor
starName = percentOfThisStar < 0.5
? "star.leadinghalf.fill" // Partial star
: "star.fill" // Full star
}
imageViews[i].image = UIImage(systemName: starName)?
.withRenderingMode(.alwaysOriginal)
.withTintColor(tintColor)
}
}
作为建议,我可能会将
fillStars
移动到代码库的另一部分。我不太确定 self
是什么(Float
?是。我可能只是让它成为自由函数,或者可能是任何包含星星的视图中的方法,并将Double
作为参数传递。我的推理只是填充星星与 Decimal
可能是的任何数字类型没有太大关系。这只是您应用程序的一种特殊情况用法,可能仅适用于您应用程序中的一个特定视图,那么为什么不将其放在该视图中呢?还是作为顶级应用程序特定功能?显然,这是一个判断电话。编译器不关心,所以这只是什么对您和您的团队最有意义的问题。为了在不创建完整应用程序的情况下更轻松地测试它(并避免必须使用模拟器),我在命令行工具中这样写:fillStars
我将review
重命名为
self
,并将其作为参数传入。我打印
enum StarType: String
{
case empty = "[ ]"
case partial = "[* ]"
case filled = "[**]"
}
func clamp<T: Comparable>(_ value: T, to range: ClosedRange<T>) -> T {
return max(range.lowerBound, min(range.upperBound, value))
}
func fillStars(
in stars: inout [StarType],
from rating: Float)
{
assert(Float(stars.count) >= rating)
for i in stars.indices
{
// Calculate the percentage of the current star to draw
let percentOfThisStar = clamp(rating - Float(i), to: 0...1)
let starType: StarType
// Now use the percentage to pick the image/tinting
if percentOfThisStar == 0
{ // Empty star
starType = .empty
}
else
{
starType = percentOfThisStar < 0.5
? .partial
: .filled
}
stars[i] = starType
}
}
,而不是实心星,对于部分星,我打印
review
,对于空星,我打印 rating
.我用这个代码驱动它:[**]
这些是结果:
评分 = 4.2,星星 = [**][**][**][**][* ]
这似乎是正确的结果。