UITableView中CardView每次显示时阴影视图逐渐变暗问题排查
问题原因分析
你遇到的阴影越来越暗的核心问题是:每次执行willDisplay时都会创建一个全新的whiteRoundedView实例,判断cell.contentView.subviews.contains(whiteRoundedView)时,这个新对象必然不在已有的子视图列表里,导致每次都会执行添加操作——多个阴影层叠加后,视觉上就会越来越暗。另外CGRectMake属于过时API,建议替换为CGRect(x:y:width:height:)。
最佳实现方案:自定义UITableViewCell(推荐)
把卡片视图的创建和样式封装到自定义Cell中,让Cell自身管理UI,既符合MVC设计逻辑,又能彻底解决复用重复添加的问题,同时适配不同屏幕尺寸。
1. 创建自定义Cell类
class CardTableViewCell: UITableViewCell { // 定义卡片视图 private let cardView: UIView = { let view = UIView() view.backgroundColor = .white view.layer.cornerRadius = 3.0 view.layer.masksToBounds = false view.layer.shadowOffset = CGSize(width: -1, height: 1) view.layer.shadowOpacity = 0.5 view.translatesAutoresizingMaskIntoConstraints = false return view }() override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) setupCellLayout() } required init?(coder: NSCoder) { super.init(coder: coder) setupCellLayout() } // 配置Cell布局 private func setupCellLayout() { contentView.backgroundColor = .clear contentView.addSubview(cardView) contentView.sendSubviewToBack(cardView) // 使用AutoLayout替代硬编码frame,适配所有屏幕 NSLayoutConstraint.activate([ cardView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 15), cardView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -15), cardView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 15), cardView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -15) ]) } }
2. 在TableView中使用自定义Cell
// 在viewDidLoad中注册Cell override func viewDidLoad() { super.viewDidLoad() tableView.register(CardTableViewCell.self, forCellReuseIdentifier: "CardCell") } // 数据源方法中复用Cell func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "CardCell", for: indexPath) as! CardTableViewCell // 这里配置Cell的内容(比如文本、图标等) return cell }
临时修复方案(不推荐)
如果不想自定义Cell,可以通过给视图加tag的方式判断是否已添加,避免重复创建:
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { cell.contentView.backgroundColor = .clear let cardTag = 1000 // 通过tag判断是否已有卡片视图 if let existingCard = cell.contentView.viewWithTag(cardTag) { cell.contentView.sendSubviewToBack(existingCard) return } let cardView = UIView(frame: CGRect(x: 15, y: 15, width: view.frame.width - 30, height: 90)) cardView.tag = cardTag cardView.backgroundColor = .white cardView.layer.cornerRadius = 3.0 cardView.layer.masksToBounds = false cardView.layer.shadowOffset = CGSize(width: -1, height: 1) cardView.layer.shadowOpacity = 0.5 cell.contentView.addSubview(cardView) cell.contentView.sendSubviewToBack(cardView) }
方案对比
自定义Cell的优势:
- 逻辑内聚,Cell的UI样式由自身管理,代码更清晰
- 避免在
willDisplay中重复操作视图,性能更优 - AutoLayout适配不同屏幕,比硬编码frame更健壮
内容的提问来源于stack exchange,提问作者Thush-Fdo
相关产品推荐
相关产品推荐

