iOS开发:基于VIPER模式,自定义UITableViewCell配置位置的疑问
Hey there! Great question—especially since you're diving into VIPER while still building up your design pattern experience. Let's break this down, keeping VIPER's core principle of separation of responsibilities front and center.
First, a Quick VIPER Reminder for Your Context
In VIPER, the ViewController falls into the View layer. Its job is to:
- Display what the Presenter provides
- Forward user interactions to the Presenter
- Avoid handling UI rendering details beyond coordinating views (like reusing table view cells)
Custom UITableViewCell subclasses are also part of the View layer, but their sole responsibility is to manage their own UI elements (your UILabels, UIImageViews, etc.).
Comparing Your Two Options
1. Modifying Cells Directly in cellForRowAt
This approach might feel straightforward at first, but it goes against VIPER's principles:
- Violates single responsibility: Your ViewController will get bloated with UI formatting logic (like setting label text colors, resizing images, etc.) that doesn't belong there.
- Hurts reusability: If you need the same cell in another ViewController, you'll have to duplicate all that formatting code.
- Makes maintenance harder: If you ever need to update the cell's UI (e.g., change a font), you'll have to hunt through the ViewController instead of going straight to the cell class.
Example of what to avoid:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell let model = dataArray[indexPath.row] // ❌ ViewController handling cell UI details cell.titleLabel.text = model.title cell.titleLabel.font = UIFont.systemFont(ofSize: 16, weight: .semibold) cell.subtitleLabel.text = model.subtitle cell.avatarImageView.image = UIImage(named: model.avatarName) cell.avatarImageView.layer.cornerRadius = 8 return cell }
2. Adding a Configuration Method to Your Custom Cell
This is the VIPER-aligned best practice. Here's why:
- Keeps responsibilities clear: The cell owns its own UI logic, so your ViewController stays focused on coordinating with the Presenter and cell reuse.
- Improves reusability: You can use this cell anywhere in your app by just calling its configuration method with the right model.
- Easier to maintain: All UI-related changes for the cell live in one place—the cell subclass.
Here's how to implement it:
Step 1: Add a Configuration Method to Your Custom Cell
class CustomCell: UITableViewCell { @IBOutlet weak var titleLabel: UILabel! @IBOutlet weak var subtitleLabel: UILabel! @IBOutlet weak var avatarImageView: UIImageView! // ✅ Cell handles its own UI configuration func configure(with model: YourModel) { titleLabel.text = model.title titleLabel.font = UIFont.systemFont(ofSize: 16, weight: .semibold) subtitleLabel.text = model.subtitle avatarImageView.image = UIImage(named: model.avatarName) avatarImageView.layer.cornerRadius = 8 } }
Step 2: Call the Method in cellForRowAt
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell let model = dataArray[indexPath.row] // ✅ ViewController only passes data to the cell cell.configure(with: model) return cell }
Bonus: VIPER-Level Enhancement
If you want to stick even closer to VIPER's strict rules, consider having your Presenter provide a ViewModel instead of passing the raw Model directly to the View layer. The ViewModel would contain exactly what the cell needs to display (e.g., formatted dates, pre-resized image data), so the cell doesn't have to transform the Model itself. But for your current use case, the configuration method on the cell is already a huge win.
Final Takeaway
Always encapsulate cell UI configuration within the custom cell subclass. This keeps your ViewController lean, follows VIPER's separation of responsibilities, and makes your code easier to maintain and reuse.
内容的提问来源于stack exchange,提问作者Sulaiman Khan

