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

Swift中UITableViewCell实现单选Radio Button问题求助

Fixing the Radio Button Selection Issue in Your Spaceship Store UITableView

Hey there! Let's sort out that annoying radio button problem where tapping one selects all in your spaceship list. I’ve dealt with this exact issue thanks to UITableView’s cell reuse behavior—here’s what’s going wrong and how to fix it step by step:

Why This Happens

UITableView reuses cells to save memory, so when you tap a radio button, the selected state gets "carried over" to other cells as they scroll into view. Without a proper way to track which spaceship is actually selected, all buttons end up showing the wrong state.

Step-by-Step Solution

1. Add a Selection Flag to Your Spaceship Model

First, update your data model to track which ship is selected. This ensures we have a single source of truth for the selection state:

struct Spaceship {
    let name: String
    let imageName: String
    // Add other properties (like price, stats) here
    var isSelected: Bool = false // Tracks if this ship is the chosen one
}

2. Configure Your UITableViewCell Properly

Modify your cell to handle the radio button state correctly, and reset state when cells are reused:

class SpaceshipCell: UITableViewCell {
    @IBOutlet weak var radioButton: UIButton!
    @IBOutlet weak var shipNameLabel: UILabel!
    
    private var onSelect: (() -> Void)?
    
    override func prepareForReuse() {
        super.prepareForReuse()
        // Reset button state to avoid reuse issues
        radioButton.isSelected = false
    }
    
    func setup(with ship: Spaceship, selectionAction: @escaping () -> Void) {
        shipNameLabel.text = ship.name
        radioButton.isSelected = ship.isSelected
        self.onSelect = selectionAction
    }
    
    @IBAction func radioButtonTapped(_ sender: UIButton) {
        onSelect?()
    }
    
    override func awakeFromNib() {
        super.awakeFromNib()
        // Set custom radio button images (if using)
        radioButton.setImage(UIImage(named: "radio_unselected"), for: .normal)
        radioButton.setImage(UIImage(named: "radio_selected"), for: .selected)
    }
}

3. Manage Selection Logic in Your View Controller

In your view controller, handle the selection to ensure only one ship is marked as selected at a time, then refresh the table:

class SpaceshipStoreVC: UIViewController, UITableViewDataSource, UITableViewDelegate {
    @IBOutlet weak var tableView: UITableView!
    private var spaceships: [Spaceship] = [
        // Populate with your spaceship data
        Spaceship(name: "Alpha Fighter", imageName: "alpha_ship"),
        Spaceship(name: "Beta Cruiser", imageName: "beta_ship"),
        Spaceship(name: "Gamma Destroyer", imageName: "gamma_ship")
    ]
    private var lastSelectedIndexPath: IndexPath? // Optional: for optimized refreshes
    
    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.register(UINib(nibName: "SpaceshipCell", bundle: nil), forCellReuseIdentifier: "SpaceshipCell")
    }
    
    // MARK: UITableView DataSource
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return spaceships.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "SpaceshipCell", for: indexPath) as! SpaceshipCell
        let ship = spaceships[indexPath.row]
        
        cell.setup(with: ship) { [weak self] in
            guard let self = self else { return }
            
            // Deselect all ships first
            self.spaceships.indices.forEach { self.spaceships[$0].isSelected = false }
            // Select the tapped ship
            self.spaceships[indexPath.row].isSelected = true
            
            // Optimized refresh: only update affected cells
            if let lastIndex = self.lastSelectedIndexPath {
                self.tableView.reloadRows(at: [lastIndex, indexPath], with: .automatic)
            } else {
                self.tableView.reloadRows(at: [indexPath], with: .automatic)
            }
            self.lastSelectedIndexPath = indexPath
        }
        
        return cell
    }
}

Quick Notes

  • If you’re using system radio buttons instead of custom images, the isSelected property will still handle the toggle state correctly.
  • Using reloadRows instead of reloadData makes the UI update smoother, especially with long lists.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 10:06:31