如何避免UITableView的cellForRowAt方法中重复代码?求解决方案
Hey there! Let's tackle that code duplication in your cellForRowAt method. The problem with your attempted refactor is that the base UITableViewCell class doesn't have a product property, so trying to assign cell.product = product throws a compiler error. Here are a couple of clean, maintainable solutions to fix this:
First, define a protocol to standardize cells that need a product property. This lets you safely set the product only on cells that support it:
// Define a protocol for cells that accept a Product protocol ProductConfigurable { var product: Product? { get set } } // Make your existing cell classes conform to the protocol extension ProductImageCell: ProductConfigurable {} extension ProductDetailCell: ProductConfigurable {} // ProductDeliveryTimeCell doesn't need a product, so no conformance needed
Now refactor your cellForRowAt method to handle dequeuing, unique cell configurations, and shared setup in one place:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell: UITableViewCell // Dequeue the correct cell type based on row switch indexPath.row { case 0: cell = tableView.dequeueReusableCell(withIdentifier: productImageCell, for: indexPath) as! ProductImageCell case 1: // Handle unique configuration for the detail cell let detailCell = tableView.dequeueReusableCell(withIdentifier: productDetailCell, for: indexPath) as! ProductDetailCell detailCell.backgroundColor = .lightGray cell = detailCell case 2...: cell = tableView.dequeueReusableCell(withIdentifier: productDeliveryCell, for: indexPath) as! ProductDeliveryTimeCell default: cell = UITableViewCell() // Fallback, won't be hit in your current setup } // Shared configuration for all cells cell.selectionStyle = .none // Set product only on cells that support it if let configurableCell = cell as? ProductConfigurable { configurableCell.product = self.product } return cell }
If you anticipate adding more cell types later, using an enum to manage cell identifiers and classes keeps your code organized and scalable:
// Enum to centralize all cell type info enum ProductCellType { case image, detail, delivery var identifier: String { switch self { case .image: return productImageCell case .detail: return productDetailCell case .delivery: return productDeliveryCell } } func cellClass() -> UITableViewCell.Type { switch self { case .image: return ProductImageCell.self case .detail: return ProductDetailCell.self case .delivery: return ProductDeliveryTimeCell.self } } } // Helper method to map indexPath to cell type func cellType(for indexPath: IndexPath) -> ProductCellType { switch indexPath.row { case 0: return .image case 1: return .detail default: return .delivery } }
Now update cellForRowAt to use this enum:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cellType = self.cellType(for: indexPath) let cell = tableView.dequeueReusableCell(withIdentifier: cellType.identifier, for: indexPath) as! UITableViewCell // Shared configuration cell.selectionStyle = .none // Handle unique cell configurations switch cellType { case .detail: if let detailCell = cell as? ProductDetailCell { detailCell.backgroundColor = .lightGray } default: break // No unique setup needed } // Set product for configurable cells if let configurableCell = cell as? ProductConfigurable { configurableCell.product = self.product } return cell }
Key Benefits
- No More Duplication: Dequeuing,
selectionStylesetup, and product configuration are handled once instead of repeating for every cell type. - Maintainability: Adding a new cell type only requires updating the enum (and protocol if needed) instead of modifying the
cellForRowAtswitch case directly. - Type Safety: The protocol ensures you only set
producton cells that actually support it, avoiding runtime errors.
内容的提问来源于stack exchange,提问作者Juri

