참조 소스 -
Create tap-able "links" in the NSAttributedString of a UILabel?
그것은 빠른 3.0
로 변환이 시도 -
스위프트 3.0 -
는 아래와 같이 UILabel의를위한 하위 클래스 만들기
01 보기 컨트롤러의 당신의
viewDidLoad
방법 내에서 23,516,
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()에 링크를 추가
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
}
}
를로 (14, 4) . 제 경우에는 링크의 범위를 알지 못합니다. 그것이 내가 원하는 것입니다. – alionthego
내 지식에 따라 UILable을 사용하여이를 달성하려면 범위를 알아야합니다. 그렇지 않으면 UITextView를 사용해야합니다. –
UITextView는 성능상의 이유로 옵션이 아닙니다. – alionthego