如何在FloatingTableView中重写不同类型的delegate属性(仿UITableView实现)
Got it, let's break down how to replicate the pattern UITableView uses with UIScrollView—subclassing UITableView to create FloatingTableView, and overriding the delegate property to use your custom FloatingTableViewDelegate protocol (which inherits from UITableViewDelegate). This relies on Swift's protocol inheritance and property covariance, just like Apple's implementation.
Step 1: Define Your Custom Delegate Protocol
First, create your FloatingTableViewDelegate protocol that inherits from UITableViewDelegate. Mark it with @objc (since UITableViewDelegate is Objective-C-compatible) and use @objc optional for custom methods so implementers can choose whether to use them:
import UIKit @objc protocol FloatingTableViewDelegate: UITableViewDelegate { // Add your custom delegate methods here @objc optional func floatingTableViewDidTriggerFloat(_ tableView: FloatingTableView) @objc optional func floatingTableView(_ tableView: FloatingTableView, didUpdateFloatState isFloating: Bool) }
Step 2: Subclass UITableView and Override the Delegate Property
Next, build your FloatingTableView subclass. We'll use a private storage variable for the custom delegate, then override the delegate property to expose the custom protocol type. We also ensure the underlying UITableView delegate points to your custom delegate (since it's compatible with UITableViewDelegate):
class FloatingTableView: UITableView { // Private storage to hold our custom delegate private weak var _floatingDelegate: FloatingTableViewDelegate? // Override the delegate property to use our custom protocol type override weak var delegate: FloatingTableViewDelegate? { get { return _floatingDelegate } set { _floatingDelegate = newValue // Pass the custom delegate to the superclass's delegate property // This works because FloatingTableViewDelegate inherits from UITableViewDelegate super.delegate = newValue } } // Optional: Add custom logic that triggers your delegate methods override func scrollViewDidScroll(_ scrollView: UIScrollView) { super.scrollViewDidScroll(scrollView) // Example: Trigger a custom delegate method when the table scrolls past a threshold let scrollThreshold = 100.0 if contentOffset.y > scrollThreshold { _floatingDelegate?.floatingTableViewDidTriggerFloat?(self) } } }
Step 3: Use Your Custom Table View and Delegate
Now you can use FloatingTableView just like a regular UITableView, with the added benefit of your custom delegate methods:
class ExampleViewController: UIViewController, FloatingTableViewDelegate { override func viewDidLoad() { super.viewDidLoad() let floatingTable = FloatingTableView(frame: view.bounds) floatingTable.delegate = self floatingTable.dataSource = self // Don't forget your data source! view.addSubview(floatingTable) // Configure table view (register cells, etc.) floatingTable.register(UITableViewCell.self, forCellReuseIdentifier: "Cell") } // MARK: - UITableViewDelegate func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { print("Selected row \(indexPath.row)") } // MARK: - FloatingTableViewDelegate func floatingTableViewDidTriggerFloat(_ tableView: FloatingTableView) { print("Table view crossed the scroll threshold and is now 'floating'!") } } // Add UITableViewDataSource conformance for completeness extension ExampleViewController: UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 20 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) cell.textLabel?.text = "Row \(indexPath.row)" return cell } }
Troubleshooting Common Issues
- Compile error about covariant types: Ensure your
FloatingTableViewDelegateexplicitly inherits fromUITableViewDelegateand is marked with@objc. Swift allows property covariance only for Objective-C-compatible protocols. - Custom delegate methods not firing: Double-check that custom methods are marked with
@objc optional, thedelegateproperty is set correctly, and your view controller conforms toFloatingTableViewDelegate. - System UITableViewDelegate methods not working: Since we set
super.delegate = newValue, standard delegate methods should work as expected. If they don't, verify your delegate implements those methods and you didn't override them inFloatingTableViewwithout callingsuper.
内容的提问来源于stack exchange,提问作者Syed Qamar Abbas

