0

I'm trying to make clickable phone numbers with UITextView. I manage to get them working with TextView created in the Storyboard and linking them over with @IBOutlet like the ones mentioned in How to display clickable links in UITextView.

But I'm not able to click TextViews that were dynamically generated and I won't have the option to simply check the Detection Links and Behavior Selectable since these TextView are created by code instead of in storyboard.

Below is one of my function to get phone numbers

private func createPhoneNumber(text: String) -> UITextView {
    let label = UITextView()
    label.isEditable = false
    label.isSelectable = true
    label.isScrollEnabled = false
    label.isUserInteractionEnabled = true
    label.dataDetectorTypes = UIDataDetectorTypes.phoneNumber
    let padding = label.textContainer.lineFragmentPadding
    label.textContainerInset = UIEdgeInsetsMake(0, -padding, 0, -padding)
    label.text = text
    return label
}

These are my other functions to dynamically generate the stackview that the label TextView and link TextView will be inside of.

private func createStackView(subViews: [UIView], xpadding: CGFloat) -> UIStackView {
    let stackView = UIStackView(arrangedSubviews: subViews)
    stackView.axis = .horizontal
    stackView.distribution = .fillEqually
    stackView.alignment = .fill
    stackView.spacing = xpadding
    stackView.translatesAutoresizingMaskIntoConstraints = false
    return stackView
}

private func createLabelValue(text: String) -> UILabel {
    let label = UILabel()
    label.font = UIFont(name: label.font.fontName, size: CGFloat(14))
    label.numberOfLines = 0
    label.lineBreakMode = NSLineBreakMode.byWordWrapping
    label.text = text
    return label
}

private func createConstraints(item: Any, toItemXW: Any, toItemY: Any, YPadding: CGFloat) -> [NSLayoutConstraint] {
    let DEFAULT_MULTIPLIER = CGFloat(1)
    let DEFAULT_PADDING = CGFloat(8)

    let xconstraint = NSLayoutConstraint(item: item, attribute: NSLayoutAttribute.leading, relatedBy: NSLayoutRelation.equal, 
        toItem: toItemXW, attribute: NSLayoutAttribute.leading, multiplier: DEFAULT_MULTIPLIER, constant: DEFAULT_PADDING)
    let yconstraint = NSLayoutConstraint(item: item, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, 
        toItem: toItemY, attribute: NSLayoutAttribute.bottom, multiplier: DEFAULT_MULTIPLIER, constant: YPadding)
    let widthConstraint = NSLayoutConstraint(item: item, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, 
        toItem: toItemXW, attribute: NSLayoutAttribute.width, multiplier: DEFAULT_MULTIPLIER, constant: 0)

    return [xconstraint, yconstraint, widthConstraint]
}

I used that function to create a phone number text link then added into a dynamically generated horizontal stackview which is added into a vertical stackview as a list.

@IBOutlet weak var stackview: UIStackView!
var prevStackView = self.stackview

let phone_label = self.createLabelValue(text: "Phone")
let phone_num = self.createPhoneNumber(text: "800-199-1999")


// Faculty Phone
let phoneStackView = self.createStackView(subViews: [phone_label, phone], xpadding: CGFloat(8))
self.stackview.addSubview(phoneStackView)
let constraintsFacultyPhone = self.createConstraints(item: phoneStackView, toItemXW: self.scroll_view, toItemY: prevStackView ?? "", YPadding: CGFloat(2))
prevStackView = phoneStackView

self.scroll_view.addConstraints(constraintsFacultyPhone)
Ben Pham
  • 1
  • 1
  • you should use tel:// before phone number to detect it as a phone number link by textview this post has clear detail https://stackoverflow.com/a/46219424/1142743 – Vinodh Mar 09 '18 at 07:43
  • Nobody even knows what createLabelTitle is. If you are creating a UILabel object with it as the name suggests, then, obviously, it's not going to work. – El Tomato Mar 09 '18 at 11:41

0 Answers0