我是子类化UITextView并在子类中实现一些委托方法,如textViewDidChangeSelection
,但我还需要在View Controller中获取UITextView委托的通知。
因此,如果我在视图控制器中创建子类的对象并设置textview委托,则仅在视图控制器中通知委托方法而不在子类内部。我需要通知这两个班级。我正在使用的语言是swift 2
我试图在子类委托中继承UITextViewDelegate:
@objc protocol CustomTextViewDelegate:UITextViewDelegate {
func customTextViewDidChangeSize(chatTextView: CustomTextView)
}
然后在VC中:
let customTV = CustomTextView()
customTV.customTextViewDelegate = self
但是没有调用任何textview委托方法。
答案 0 :(得分:1)
好问题。这不是一个很好的答案,因为它要求您重写所有委托方法,因此,如果委托方法随时间变化,则在iOS版本之间不稳定。
通过这种方法,ViewController
和CustomTextField
都可以访问委托事件。
class CustomTextView: UITextView {
override var delegate: UITextViewDelegate? {
set {
superDelegate = newValue
} get {
return superDelegate
}
}
private weak var superDelegate: UITextViewDelegate?
init() {
super.init(frame: .zero, textContainer: nil)
super.delegate = self
}
func textDidChange(text: String?) {
// do something
}
}
extension BoundTextView: UITextViewDelegate {
public func textViewDidChange(_ textView: UITextView) {
// catch text-change events here
textDidChange(text: String?)
superDelegate?.textViewDidChange?(textView)
}
public func textViewDidEndEditing(_ textView: UITextView) {
superDelegate?.textViewDidEndEditing?(textView)
}
public func textViewDidChangeSelection(_ textView: UITextView) {
superDelegate?.textViewDidChange?(textView)
}
public func textViewShouldBeginEditing(_ textView: UITextView) -> Bool {
return superDelegate?.textViewShouldBeginEditing?(textView) ?? false
}
public func textViewDidBeginEditing(_ textView: UITextView) {
superDelegate?.textViewDidBeginEditing?(textView)
}
public func textViewShouldEndEditing(_ textView: UITextView) -> Bool {
return superDelegate?.textViewShouldEndEditing?(textView) ?? false
}
public func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
return superDelegate?.textView?(textView, shouldChangeTextIn: range, replacementText: text) ?? false
}
public func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
return superDelegate?.textView?(textView, shouldInteractWith: URL, in: characterRange, interaction: interaction) ?? false
}
public func textView(_ textView: UITextView, shouldInteractWith textAttachment: NSTextAttachment, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
return superDelegate?.textView?(textView, shouldInteractWith: textAttachment, in: characterRange, interaction: interaction) ?? false
}
}
我们重写delegate
并将其引用存储在单独的变量(称为superDelegate
)中。 CustomTextField将自身分配给super.delegate
并实现UITextView-delegate
。我们必须确保每个委托事件都会触发相应的superDelegate
事件。
我们的“ ViewController”现在可以将自己分配为CustomTextView
的委托人:
class ViewController: UIViewController {
...
lazy var textField: CustomTextView {
let textView = CustomTextField()
textView.delegate = self
return textField
}()
...
}
extension ViewController: UITextViewDelegate {
// implement only the delegate-methods you need
}
现在ViewController
和CustomTextField
都可以访问UITextFieldDelegate
。
答案 1 :(得分:0)
两个对象不能同时委托给UITextView
对象。因此,您应为CustomTextViewDelegate
创建新协议(CustomTextView
)并在其中创建委托属性。让您的ViewController
确认此CustomTextViewDelegate
并实施其方法。在CustomTextView
UITextViewDelegate
方法的实施中,您可以调用适当的CustomTextViewDelegate
方法。
答案 2 :(得分:0)
@nayooti 的方法非常好。但是,我必须做一些修复才能正常工作。主要的问题是某些委托方法不会被调用(例如 shouldChangeTextIn range
,因此 textViewDidChange
也是如此)。
我发现可以通过在覆盖的 super.delegate
变量的 get 访问器上返回 superDelegate
而不是 delegate
来修复它。
class CustomTextView: UITextView {
override var delegate: UITextViewDelegate? {
set {
superDelegate = newValue
} get {
return super.delegate
}
}
private weak var superDelegate: UITextViewDelegate?
init() {
super.init(frame: .zero, textContainer: nil)
super.delegate = self
}
override public init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer)
super.delegate = self
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
super.delegate = self
}
func textDidChange(text: String?) {
// Do something
}
}
extension CustomTextView: UITextViewDelegate {
public func textViewDidChange(_ textView: UITextView) {
// Catch text-change events here
textDidChange(text: textView.text)
superDelegate?.textViewDidChange?(textView)
}
public func textViewDidEndEditing(_ textView: UITextView) {
superDelegate?.textViewDidEndEditing?(textView)
}
public func textViewDidChangeSelection(_ textView: UITextView) {
superDelegate?.textViewDidChange?(textView)
}
public func textViewShouldBeginEditing(_ textView: UITextView) -> Bool {
return superDelegate?.textViewShouldBeginEditing?(textView) ?? true
}
public func textViewDidBeginEditing(_ textView: UITextView) {
superDelegate?.textViewDidBeginEditing?(textView)
}
public func textViewShouldEndEditing(_ textView: UITextView) -> Bool {
return superDelegate?.textViewShouldEndEditing?(textView) ?? true
}
public func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
return superDelegate?.textView?(textView, shouldChangeTextIn: range, replacementText: text) ?? true
}
public func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
return superDelegate?.textView?(textView, shouldInteractWith: URL, in: characterRange, interaction: interaction) ?? true
}
public func textView(_ textView: UITextView, shouldInteractWith textAttachment: NSTextAttachment, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
return superDelegate?.textView?(textView, shouldInteractWith: textAttachment, in: characterRange, interaction: interaction) ?? true
}
}