Ios firstRect(for:)在UITextField中返回错误的值
我正在尝试使用语法高亮显示来标记用户输入中的错误 遵循代码中的建议对于UITextView非常有效Ios firstRect(for:)在UITextField中返回错误的值,ios,swift,Ios,Swift,我正在尝试使用语法高亮显示来标记用户输入中的错误 遵循代码中的建议对于UITextView非常有效 func findRect(forTextMatching match:String, in textView:UITextView) -> CGRect? { if let text = textView.text, let range = text.range(of: match) { let offset1 = text.distance(
func findRect(forTextMatching match:String, in textView:UITextView) -> CGRect? {
if let text = textView.text,
let range = text.range(of: match)
{
let offset1 = text.distance(from: text.startIndex, to: range.lowerBound)
let offset2 = text.distance(from: text.startIndex, to: range.upperBound)
if let pos1 = textView.position(from: textView.beginningOfDocument, offset: offset1),
let pos2 = textView.position(from: textView.beginningOfDocument, offset: offset2)
{
if let textRange = textView.textRange(from: pos1, to: pos2)
{
textView.selectedTextRange = textRange
let rect = textView.firstRect(for: textRange)
return rect
}
}
}
return nil
}
然而,我现在正试图为UITextField做类似的事情,但遇到了麻烦
UITextField和UITextView都符合UITEPUT,定位rect所需的所有方法都应适用于这两种方法
这是UITextView的一个函数
func findRect(forTextMatching match:String, in textView:UITextView) -> CGRect? {
if let text = textView.text,
let range = text.range(of: match)
{
let offset1 = text.distance(from: text.startIndex, to: range.lowerBound)
let offset2 = text.distance(from: text.startIndex, to: range.upperBound)
if let pos1 = textView.position(from: textView.beginningOfDocument, offset: offset1),
let pos2 = textView.position(from: textView.beginningOfDocument, offset: offset2)
{
if let textRange = textView.textRange(from: pos1, to: pos2)
{
textView.selectedTextRange = textRange
let rect = textView.firstRect(for: textRange)
return rect
}
}
}
return nil
}
在测试应用程序中运行此命令,并突出显示返回矩形,如下所示:
现在尝试对UITextField执行相同的操作:
func findRect(forTextMatching match:String, in textField:UITextField) -> CGRect? {
if let text = textField.text,
let range = text.range(of: match)
{
let offset1 = text.distance(from: text.startIndex, to: range.lowerBound)
let offset2 = text.distance(from: text.startIndex, to: range.upperBound)
// beginningOfDocument is nil unless textField is first responder
textField.becomeFirstResponder()
defer {
textField.resignFirstResponder()
}
if let pos1 = textField.position(from: textField.beginningOfDocument, offset: offset1),
let pos2 = textField.position(from: textField.beginningOfDocument, offset: offset2)
{
if let textRange = textField.textRange(from: pos1, to: pos2)
{
textField.selectedTextRange = textRange
var rect = textField.firstRect(for: textRange)
return rect
}
}
}
return nil
}
func findRect(forTextMatching match:String, in textField:UITextField) -> CGRect? {
if let text = textField.text,
let range = text.range(of: match)
{
let offset1 = text.distance(from: text.startIndex, to: range.lowerBound)
let offset2 = text.distance(from: text.startIndex, to: range.upperBound)
// beginningOfDocument is nil unless textField is first responder
textField.becomeFirstResponder()
defer {
textField.resignFirstResponder()
}
if let pos1 = textField.position(from: textField.beginningOfDocument, offset: offset1),
let pos2 = textField.position(from: textField.beginningOfDocument, offset: offset2)
{
if let textRange = textField.textRange(from: pos1, to: pos2)
{
var rect = textField.firstRect(for: textRange)
// firstRect is actually relative to editingRect, not textField
let top = textField.editingRect(forBounds: textField.bounds).origin.y
let left = textField.editingRect(forBounds: textField.bounds).origin.x
rect = CGRect(x: rect.origin.x+left, y: rect.origin.y+top, width: rect.width, height: rect.height)
return rect
}
}
}
return nil
}
第一个问题是UITextField.beginingofdocument为零,除非该字段是第一响应者。这很容易处理,因此有额外的线路成为第一响应者和第一响应者
在测试应用程序中运行此命令,并突出显示返回的rect,如下所示:
返回的rect略微偏移。这似乎是UITextField的错误。在调试中检查视图层次结构时,UIFieldEditor类型的UIExtField下有一个额外的视图,具有帧原点(7,4)。返回的rect似乎与此视图相关,而不是UITextField 事实证明,您可以作为UITextField的editRect访问此帧 修改了UITextField的func:
func findRect(forTextMatching match:String, in textField:UITextField) -> CGRect? {
if let text = textField.text,
let range = text.range(of: match)
{
let offset1 = text.distance(from: text.startIndex, to: range.lowerBound)
let offset2 = text.distance(from: text.startIndex, to: range.upperBound)
// beginningOfDocument is nil unless textField is first responder
textField.becomeFirstResponder()
defer {
textField.resignFirstResponder()
}
if let pos1 = textField.position(from: textField.beginningOfDocument, offset: offset1),
let pos2 = textField.position(from: textField.beginningOfDocument, offset: offset2)
{
if let textRange = textField.textRange(from: pos1, to: pos2)
{
textField.selectedTextRange = textRange
var rect = textField.firstRect(for: textRange)
return rect
}
}
}
return nil
}
func findRect(forTextMatching match:String, in textField:UITextField) -> CGRect? {
if let text = textField.text,
let range = text.range(of: match)
{
let offset1 = text.distance(from: text.startIndex, to: range.lowerBound)
let offset2 = text.distance(from: text.startIndex, to: range.upperBound)
// beginningOfDocument is nil unless textField is first responder
textField.becomeFirstResponder()
defer {
textField.resignFirstResponder()
}
if let pos1 = textField.position(from: textField.beginningOfDocument, offset: offset1),
let pos2 = textField.position(from: textField.beginningOfDocument, offset: offset2)
{
if let textRange = textField.textRange(from: pos1, to: pos2)
{
var rect = textField.firstRect(for: textRange)
// firstRect is actually relative to editingRect, not textField
let top = textField.editingRect(forBounds: textField.bounds).origin.y
let left = textField.editingRect(forBounds: textField.bounds).origin.x
rect = CGRect(x: rect.origin.x+left, y: rect.origin.y+top, width: rect.width, height: rect.height)
return rect
}
}
}
return nil
}
生成正确的结果:
务必提交雷达文件。¯_(ツ)_/¯