ios - 关于在 Swift 中删除对 Delegate Class 和 ViewController 的直接引用的问题
问题描述
我正在制作一个注册屏幕。我将 4 个 TextFields 作为 @IBOutlet Collection 连接到 ViewController。我创建了一个单独的 TextFieldDelegate 类来管理 UITextFieldDelegate。这里的问题是 TextFieldDelegate 直接引用 ViewController 来访问 TextField 集合。
TextFieldDelegate.swift
class TextFieldDelegate: NSObject, UITextFieldDelegate {
private weak var signUpViewController: SignUpViewController?
init(_ signUpViewController: SignUpViewController) {
self.signUpViewController = signUpViewController
}
func textFieldDidBeginEditing(_ textField: UITextField) {
textField.layer.borderWidth = 1
textField.layer.borderColor = UIColor.systemBlue.cgColor
}
func textFieldDidChangeSelection(_ textField: UITextField) {
guard let index = self.signUpViewController?.signUpTextFields.firstIndex(of: textField) else { return }
guard let validatable = self.signUpViewController?.mapping(by: index) else { return }
}
SignUpViewController.swift
class SignUpViewController: UIViewController {
@IBOutlet var signUpTextFields: [UITextField]! {
didSet {
signUpTextFields.forEach { textField in
textField.delegate = textFieldDelegate
textField.returnKeyType = .next
}
}
}
private lazy var textFieldDelegate = TextFieldDelegate(self)
}
问题代码
private weak var signUpViewController: SignUpViewController?
init(_ signUpViewController: SignUpViewController) {
self.signUpViewController = signUpViewController
}
此问题中的代码是 TextFieldDelegate 直接引用 ViewController 的地方。除了直接引用此代码之外,还有其他方法可以访问 ViewController 吗?如果没有,我应该在需要访问 SignUpViewController 的 ViewController 中编写代码吗?
解决方案
这不是一个特别的“Swift 问题”,而是软件设计的一般问题。不过,我完全明白你为什么认为这是一个问题。
您可以使用事件或多个 Observable 替换直接引用,例如使用 RxSwift。然后,您SignUpViewController
只需订阅您TextFieldDelegate
触发的事件。
import Foundation
import UIKit
import RxSwift
class TextFieldDelegate: NSObject, UITextFieldDelegate {
private let _didChangeSelection = PublishSubject<UITextField>()
func textFieldDidChangeSelection(_ textField: UITextField) {
_didChangeSelection.onNext(textField)
}
var didChangeSelection: Observable<UITextField> {
return _didChangeSelection
}
}
class SignUpViewController: UIViewController {
//[...]
private let disposables = DisposeBag()
private func initSubscriptions() {
Observable.merge(
signupTextFields.compactMap {
$0.delegate as? TextFieldDelegate
}.map {
$0.didChangeSelection
}
).subscribe(onNext: { [weak self] textField in
guard let index = self?.signUpTextFields.firstIndex(of: textField) else { return }
guard let validatable = self?.mapping(by: index) else { return }
//Your subscription code
}).disposed(by: disposables)
}
}
推荐阅读
- python - 在python中将分类变量转换为定量变量
- javascript - 使用 jQuery 在某个设备宽度后添加一个 tr
- python - Python如何使用多处理读取和写入不同的文件
- google-api - Gmail API 信用卡信息
- html - 在图像上设置 cut-div 的问题
- javascript - 光标在替换时卡在上标或下标中
- java - 如何转换可选
列出 - plsql - 执行立即错误:PL/SQL:数字或值错误:字符到数字的转换错误
- ios - 如何减少 iOS 上的视频处理时间?
- reactjs - React Router - 通过道具将匹配传递给使用 Route::render 渲染的组件