4

채팅 앱을 만들고 있는데 성능상의 이유로 UITextView 대신 UILabel을 사용하여 채팅 메시지를 표시해야합니다. 이전에 TextView를 사용했지만 스크롤 속도가 느리거나 화면이 고르지 않습니다.UITextView를 사용하지 않고 UILabel에서 클릭 연결을 검색하고 만들려면 어떻게해야합니까?

현재 UILabels에 대한 링크/전화/주소 등의 검색이 없습니다.

문자열에 링크 또는 전화 번호가있는 위치를 확인한 다음 강조 표시하고 UILabel 내에서 클릭 할 수있게하려면 어떻게해야합니까?

링크를위한 속성을 추가하는 방법에 대한 기사를 많이 읽었지만 범위 또는 하위 문자열을 알고있는 링크는 모두 있습니다.

문자열을 가져 와서 링크가 있는지 여부와 그 링크가 어디에 있는지 확인한 다음 tapGestureRecognizer를 레이블에 추가하고 탭 발생 위치를 기반으로 작업을 수행하고 싶습니다.

외부 라이브러리 (TTTAttributedLabel)를 통합하려했지만 swift를 사용하고 있으며 swift에 대한 설명서가 제한적으로 발견되었습니다. 라이브러리를 가져 왔지만 링크가 자동으로 검색되지 않습니다.

답변

2

참조 소스 -

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 
    } 
} 
+1

를로 (14, 4) . 제 경우에는 링크의 범위를 알지 못합니다. 그것이 내가 원하는 것입니다. – alionthego

+0

내 지식에 따라 UILable을 사용하여이를 달성하려면 범위를 알아야합니다. 그렇지 않으면 UITextView를 사용해야합니다. –

+0

UITextView는 성능상의 이유로 옵션이 아닙니다. – alionthego