问题描述
我有一个自定义的 UITextView 类,用于初始化一个新的 TextView。这个类的委托本身就是因为我需要在文本更改时运行代码,委托方法运行。这是那堂课。
protocol TextViewOuterDelegate: class {
func textViewDidChange(_ textView: UITextView)
}
/// Custom `UITextView`
class TextView: UITextView,UITextViewDelegate {
var hintLabel,smallHintLabel: UILabel!
var underline: UIView!
var secondDelegate: TextViewOuterDelegate?
// MARK: - Init
/// Initialize text field
/// - Parameters:
/// - text: Text field text
/// - hintText: Text field hint text (a.k.a. placeholder/description)
/// - isLight: Whether text field is light style
convenience init(text: String? = nil,hintText: String,isLight: Bool = false) {
self.init(frame: .zero,textContainer: nil)
self.heightAnchor.constraint(equalToConstant: 57).isActive = true
self.textContainerInset = UIEdgeInsets(top: 25,left: 0,bottom: 0,right: 0)
self.delegate = self
let weight: UIFont.Weight = isLight ? .medium : .regular
let textColor: UIColor = isLight ? .white : .black
let hintColor = isLight ? UIColor(white: 1.0,alpha: 0.8) : UIColor(white: 0.0,alpha: 0.4)
let lineColor = isLight ? UIColor(white: 1.0,alpha: 0.3) : UIColor(white: 0.0,alpha: 0.12)
let largeSize = UIFont.preferredFont(forTextStyle: .title3).pointSize
let smallSize = UIFont.preferredFont(forTextStyle: .subheadline).pointSize
// hint
hintLabel = UILabel()
hintLabel.text = hintText
hintLabel.font = UIFont.systemFont(ofSize: largeSize,weight: weight)
hintLabel.textColor = hintColor
hintLabel.alpha = text == nil || text!.isBlank ? 1 : 0
self.addSubview(hintLabel)
hintLabel.translatesAutoresizingMaskIntoConstraints = false
hintLabel.centerYAnchor.constraint(equalTo: self.centerYAnchor,constant: insets.top / 2).isActive = true
hintLabel.leadingAnchor.constraint(equalTo: self.leadingAnchor,constant: insets.left
).isActive = true
hintLabel.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
// small hint
smallHintLabel = UILabel()
self.smallHintLabel.text = hintText
self.smallHintLabel.font = UIFont.systemFont(ofSize: smallSize,weight: weight)
self.smallHintLabel.textColor = hintColor
self.smallHintLabel.alpha = text == nil || text!.isBlank ? 0 : 1
self.addSubview(smallHintLabel)
smallHintLabel.translatesAutoresizingMaskIntoConstraints = false
smallHintLabel.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
smallHintLabel.leadingAnchor.constraint(equalTo: self.leadingAnchor,constant: insets.left).isActive = true
smallHintLabel.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
// text
self.text = text
self.font = UIFont.systemFont(ofSize: largeSize,weight: weight)
self.textColor = textColor
self.tintColor = isLight ? .white : Color.blue
self.keyboardAppearance = isLight ? .dark : .light
self.isScrollEnabled = false
// underline
underline = UIView()
underline.backgroundColor = lineColor
self.addSubview(underline)
underline.translatesAutoresizingMaskIntoConstraints = false
underline.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
underline.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
underline.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
underline.heightAnchor.constraint(equalToConstant: 1).isActive = true
}
override init(frame: CGRect,textContainer: NSTextContainer?) {
super.init(frame: frame,textContainer: textContainer)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
func textViewDidChange(_ textView: UITextView) {
/// Adjusts the position of the hint text when text is changed in field
if self.text?.isEmpty ?? true {
self.moveHintDown()
} else {
self.moveHintUp()
}
secondDelegate?.textViewDidChange(self)
/// Adjusts the size of the text view when text is changed in field
let size = CGSize(width: textView.visibleSize.width,height: 999999)
let estimatedSize = self.sizeThatFits(size)
self.constraints.forEach { constraint in
if constraint.firstAttribute == .height {
//Todo: Max num of lines (prob no restriction),scroll the messages every time that a new line is added,fix this code to make it nicer
if estimatedSize.height < 57 {
constraint.constant = 57
} else {
constraint.constant = estimatedSize.height
}
}
}
}
为了在每次更改不同文件的文本时运行一个函数,我设置了一个 TextViewOuterDelegate,它应该与我的另一个文件通信以运行另一个函数。
class MessageComposeView: UIView,TextViewOuterDelegate {
private var textField: TextView!
private var sendButton: SendButton!
weak var delegate: MessageComposeViewDelegate?
init() {
super.init(frame: .zero)
// text field
textField = TextView(hintText: "Type a message")
let test = TextView()
test.secondDelegate = self
self.addSubview(textField)
textField.translatesAutoresizingMaskIntoConstraints = false
textField.topAnchor.constraint(equalTo: self.topAnchor,constant: 30).isActive = true
textField.bottomAnchor.constraint(equalTo: self.bottomAnchor,constant: -30).isActive = true
textField.leadingAnchor.constraint(equalTo: self.leadingAnchor,constant: 16).isActive = true
// send button
sendButton = SendButton()
sendButton.setState(.disabled)
sendButton.addTarget(self,action: #selector(send),for: .touchUpInside)
self.addSubview(sendButton)
sendButton.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
sendButton.leadingAnchor.constraint(equalTo: textField.trailingAnchor,constant: 16).isActive = true
sendButton.trailingAnchor.constraint(equalTo: self.trailingAnchor,constant: -16).isActive = true
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
// MARK: - Actions
/// Called when the message text changes
func textViewDidChange(_ textView: UITextView) {
sendButton.setState(textField.text?.isBlank == true ? .disabled : .normal)
}
/// Calls `sendMessage(text: String?)` delegate method to send the message and disable the send button
/// Called when message is sent to reset the compose view
func sent() {
textField.text = nil
textViewDidChange(textField)
sendButton.stopLoad()
sendButton.setState(.disabled)
}
}
未设置 secondDelegate,因此 TextViewDidChange 函数未运行。我究竟做错了什么?提前致谢。
解决方法
// This is the instance that you should assign secondDelegate for
textField = TextView(hintText: "Type a message")
// Not this one,this one never gets added as a subview
let test = TextView()
test.secondDelegate = self
// The fix is here
textField.secondDelegate = self
self.addSubview(textField)