4

Я создаю приложение чата и по соображениям производительности мне нужно использовать UILabel вместо UITextView для отображения сообщений чата. Я ранее использовал TextView, но с обнаружением данных в прокрутке очень медленно и прерывисто.Как я могу обнаружить и сделать ссылки на клики в UILabel НЕ используя UITextView

Проблема в том, что в настоящее время нет ссылок/телефонов/адресов и т. Д. Обнаружение для UILabels.

Как узнать, где в строке есть ссылка или номер телефона, а затем выделить и сделать ее интерактивной в пределах UILabel?

Я прочитал много статей о том, как добавить атрибуты для ссылок, чтобы сделать это, но все они были ссылками, которые вы знаете, диапазон или подстрока.

Я хотел бы взять любую строку и выяснить, содержит ли ссылки и где эти ссылки, а затем добавить tapGestureRecognizer в метку и выполнить действия, основанные на том, где произошел ответ.

Я попытался включить внешнюю библиотеку (TTTAttributedLabel), но я использую swift и нашел документацию для быстрого ограничения. Мне удалось импортировать библиотеку, но ссылки не были автоматически обнаружены.

ответ

2

Ссылка источник -

Create tap-able "links" in the NSAttributedString of a UILabel?

преобразуется в стремительной 3.0

Попробуйте это -

Создать класс суб для UILabel, как показано ниже -

Swift 3.0

class CustomLabel: UILabel { 

let layoutManager = NSLayoutManager() 
let textContainer = NSTextContainer(size: CGSize.zero) 
var textStorage = NSTextStorage() { 
    didSet { 
     textStorage.addLayoutManager(layoutManager) 
    } 
} 
var onCharacterTapped: ((_ label: UILabel, _ characterIndex: Int) -> Void)? 

let tapGesture = UITapGestureRecognizer() 

override var attributedText: NSAttributedString? { 
    didSet { 
     if let attributedText = attributedText { 
      textStorage = NSTextStorage(attributedString: attributedText) 
     } else { 
      textStorage = NSTextStorage() 
     } 
    } 
} 
override var lineBreakMode: NSLineBreakMode { 
    didSet { 
     textContainer.lineBreakMode = lineBreakMode 
    } 
} 

override var numberOfLines: Int { 
    didSet { 
     textContainer.maximumNumberOfLines = numberOfLines 
    } 
} 

required init?(coder aDecoder: NSCoder) { 
    super.init(coder: aDecoder) 
    setUp() 
} 

override init(frame: CGRect) { 
    super.init(frame: frame) 
    setUp() 
} 
func setUp() { 
    isUserInteractionEnabled = true 
    layoutManager.addTextContainer(textContainer) 
    textContainer.lineFragmentPadding = 0 
    textContainer.lineBreakMode = lineBreakMode 
    textContainer.maximumNumberOfLines = numberOfLines 
    tapGesture.addTarget(self, action: #selector(CustomLabel.labelTapped(_:))) 
    addGestureRecognizer(tapGesture) 
} 

override func layoutSubviews() { 
    super.layoutSubviews() 
    textContainer.size = bounds.size 
} 

func labelTapped(_ gesture: UITapGestureRecognizer) { 
    guard gesture.state == .ended else { 
     return 
    } 
    let locationOfTouch = gesture.location(in: gesture.view) 
    let textBoundingBox = layoutManager.usedRect(for: textContainer) 
    let textContainerOffset = CGPoint(x: (bounds.width - textBoundingBox.width)/2 - textBoundingBox.minX, 
             y: (bounds.height - textBoundingBox.height)/2 - textBoundingBox.minY) 
    let locationOfTouchInTextContainer = CGPoint(x: locationOfTouch.x - textContainerOffset.x, y: locationOfTouch.y - textContainerOffset.y) 
    let indexOfCharacter = layoutManager.characterIndex(for: locationOfTouchInTextContainer, 
                 in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil) 

    onCharacterTapped?(self, indexOfCharacter) 
} 

} 

В вашем viewDidLoad метода View контроллера создать экземпляр этого класса, как показано ниже -

override func viewDidLoad() { 
    super.viewDidLoad() 
    // Do any additional setup after loading the view, typically from a nib. 

    let label = CustomLabel() 
    label.translatesAutoresizingMaskIntoConstraints = false 
    view.addSubview(label) 
    view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-[view]-|", 
                     options: [], metrics: nil, views: ["view" : label])) 
    view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-[view]-|", 
                     options: [], metrics: nil, views: ["view" : label])) 

    let attributedString = NSMutableAttributedString(string: "String with a link", attributes: nil) 
    let linkRange = NSMakeRange(14, 4); // for the word "link" in the string above 

    let linkAttributes: [String : AnyObject] = [ 
     NSForegroundColorAttributeName : UIColor.blue, NSUnderlineStyleAttributeName : NSUnderlineStyle.styleSingle.rawValue as AnyObject, 
     NSLinkAttributeName: "http://www.apple.com" as AnyObject] 
    attributedString.setAttributes(linkAttributes, range:linkRange) 

    label.attributedText = attributedString 

    label.onCharacterTapped = { label, characterIndex in 

     // DO YOUR STUFF HERE 
    } 
} 
+1

вы добавляете ссылку в viewDidLoad(), который вы знаете диапазон быть (14, 4) , В моем случае я не знаю диапазон ссылок. Это то, что я хочу определить. – alionthego

+0

Согласно моим знаниям, если вы хотите достичь этого с помощью UILable, вам следует знать диапазон, иначе вы должны пойти с UITextView. –

+0

UITextView не является вариантом для повышения производительности. – alionthego