You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义星级评分显示异常:4.2分未正确显示4满星1半星

星级评分显示异常问题

我在Storyboard中添加了5个UIImageView,关联的输出口如下:

@IBOutlet var starRatingImageViews: [UIImageView]!

从JSON获取的评分是字符串类型,示例为rating = "4.2"。预期显示4个满星+1个半星,但实际显示不符合预期,当前评分"4.2"对应的星星显示错误。

调用代码及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)
           }
       }
   }
}

请问fillStars方法存在哪些问题?


问题分析与修正

你的fillStars方法主要存在逻辑冗余、无范围限制两个核心问题,同时可以优化可读性:

关键问题点

  1. 未限制评分范围:若评分超过星星总数(比如6.0)或为负数,会出现索引越界或异常显示
  2. 逻辑嵌套冗余:重复计算差值、条件判断层级过多,易出错
  3. 变量命名不直观:review这类命名无法清晰表达含义

修正后的代码

extension Float {
    func fillStars(in imageViews: [UIImageView], withEmptyStarColor color: UIColor = .darkGray) {
        let maxStars = Float(imageViews.count)
        // 限制评分在0到星星总数之间,避免异常
        let clampedRating = max(0, min(self, maxStars))
        // 计算满星数量
        let fullStarCount = Int(clampedRating)
        // 计算剩余的小数部分评分
        let remainder = clampedRating - Float(fullStarCount)
        
        for (index, imageView) in imageViews.enumerated() {
            imageView.contentMode = .scaleAspectFit
            
            if index < fullStarCount {
                // 显示满星
                imageView.image = UIImage(systemName: "star.fill")?
                    .withRenderingMode(.alwaysOriginal)
                    .withTintColor(CommonColor.yellowColor)
            } else if index == fullStarCount, remainder > 0 {
                // 剩余评分>0.5时显示满星,否则显示半星
                // 若需要右半星,将图标名改为"star.trailinghalf.fill"
                let starIconName = remainder > 0.5 ? "star.fill" : "star.leadinghalf.fill"
                imageView.image = UIImage(systemName: starIconName)?
                    .withRenderingMode(.alwaysOriginal)
                    .withTintColor(CommonColor.yellowColor)
            } else {
                // 显示空星
                imageView.image = UIImage(systemName: "star")?
                    .withRenderingMode(.alwaysOriginal)
                    .withTintColor(color)
            }
        }
    }
}

额外检查项

请确认starRatingImageViews数组在Storyboard中的顺序:数组第一个元素对应界面最左侧的星星,最后一个元素对应最右侧的星星,顺序颠倒会导致显示错位。

内容的提问来源于stack exchange,提问作者swift doubts

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 01:42:20