iOS/Swift技术问题:如何为多个视图控制器添加同一扩展?
Hey there! Let's tackle this problem where you want to share keyboard/view-related code between LocationViewController and TempConvertViewController without duplicating it—especially since the activeTextField variable was holding you back from using a shared extension.
The key here is to define a protocol that enforces the activeTextField property, then build your shared logic in an extension on that protocol. This way, any view controller conforming to the protocol will have access to the reusable code, and the extension will recognize activeTextField because the protocol guarantees it exists.
Step 1: Create a Protocol with Required Property
First, make a protocol that both view controllers will adopt. This protocol will require the activeTextField property, so the extension knows it can safely use this variable.
protocol TextFieldKeyboardManager: UIViewController { var activeTextField: UITextField? { get set } }
Step 2: Conform Both View Controllers to the Protocol
Update both LocationViewController and TempConvertViewController to conform to this protocol, ensuring each has the activeTextField property defined.
For TempConvertViewController (you likely already have this, but just to confirm):
class TempConvertViewController: UIViewController, TextFieldKeyboardManager { var activeTextField: UITextField? // Rest of your existing view controller code... }
For LocationViewController:
class LocationViewController: UIViewController, TextFieldKeyboardManager { var activeTextField: UITextField? // Rest of your existing view controller code... }
Step 3: Add Reusable Code to the Protocol Extension
Now you can write all your keyboard/view-related logic in an extension on TextFieldKeyboardManager. Since the protocol guarantees activeTextField exists, the extension can access it without issues.
extension TextFieldKeyboardManager { // Example: Dismiss keyboard when tapping outside the text field func setupTapToDismissKeyboard() { let tapGesture = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard)) view.addGestureRecognizer(tapGesture) } @objc func dismissKeyboard() { activeTextField?.resignFirstResponder() } // Add other reusable methods here—like keyboard frame adjustment, text field validation, etc. }
Step 4: Use the Shared Code in Your View Controllers
Call the shared methods from either view controller's lifecycle methods (like viewDidLoad), and don't forget to update activeTextField when text fields start/end editing.
For example, in TempConvertViewController:
override func viewDidLoad() { super.viewDidLoad() setupTapToDismissKeyboard() // Uses the shared extension method // Assign text field delegate to track active text field temperatureTextField.delegate = self } // Implement UITextFieldDelegate to update activeTextField extension TempConvertViewController: UITextFieldDelegate { func textFieldDidBeginEditing(_ textField: UITextField) { activeTextField = textField } func textFieldDidEndEditing(_ textField: UITextField) { activeTextField = nil } }
Repeat the same delegate setup for LocationViewController to track its text fields.
Why This Works
By using a protocol, we create a "contract" that both view controllers follow—including having the activeTextField property. The extension on the protocol can then safely use this property, since it knows any conforming class will have it implemented. This eliminates code duplication and keeps your view controllers focused on their unique logic.
内容的提问来源于stack exchange,提问作者RochNoure

