How to use UITableView and NSLink together in Swift iOS?
How to use UITableView and NSLink together in Swift iOS?
Extension Code:
extension String
func accentTagAndLink(tags:Array<String>) -> NSMutableAttributedString
let attributedString:NSMutableAttributedString = NSMutableAttributedString(string: self)
var NSContents = self as NSString
for tagChild in tags
if !tagChild.starts(with: "<")
let range = NSContents.range(of: "#" + tagChild)
var changeString = ""
for _ in 0..<tagChild.count
changeString += "$"
NSContents = NSContents.replacingOccurrences(of: tagChild, with: changeString, options: .literal, range: range) as NSString
attributedString.addAttribute(.link, value: tagChild, range: range)
attributedString.addAttribute(.foregroundColor, value: UIColor(red: 79/255, green: 205/255, blue: 255/255, alpha: 1), range: range)
return attributedString
TableViewCell :
class PostCell: TableViewCell
@IBOutlet weak var postContent: UITextView!
in mainViewController
class PostViewController: UIViewController, UITableViewDataSource, UITableViewDelegate,UITextViewDelegate
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = postTableView.dequeueReusableCell(withIdentifier: "PostCell", for: indexPath) as! PostCell
let post = postList[indexPath.row]
let tags = (post["Content"] as! String).FindTagAtString()
cell.postContent.delegate = self
cell.postContent.isSelectable = true
cell.postContent.isEditable = false
cell.postContent.isUserInteractionEnabled = true
cell.postContent.dataDetectorTypes = UIDataDetectorTypes.link
cell.postContent.attributedText = (post["Content"] as! String).accentTagAndLink(tags: tags)
let tap = MyTapGesture(target: self, action: #selector(self.tapTextView))
tap.indexPath = indexPath
cell.postContent.addGestureRecognizer(tap)
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool
print(URL)
return true
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
print("cell tap")
movePostDetail(indexPath)
@objc func tapTextView(sender:MyTapGesture)
print("cell tap")
movePostDetail(sender.indexPath)
MyTapGesture :
class MyTapGesture: UITapGestureRecognizer
var indexPath:IndexPath!
Content is NormalText + TagText
NormalText + TagText
If tap NormalText to run movePostDetail and if tap TagText to run print(URL) but always movePostDetail when addGestureRecognizer
addGestureRecognizer
How to use together
It worked well when I took TTTAttributedLabel
, but because of crash so i haven't used TTTAttributedLabel
.
TTTAttributedLabel
TTTAttributedLabel
1 Answer
1
I advice you to use a CUSTOM ATTRIBUTE NAME and handle the tap by yourself.
Solution in Swift 4
override func awakeFromNib()
super.awakeFromNib()
// Initialization code
let tapGes = UITapGestureRecognizer(target: self, action: #selector(TableViewCell.handleTap(sender:)))
contentTf.addGestureRecognizer(tapGes)
let attributeName = "CustomAttributeName"
let attStr = NSAttributedString(string: "https", attributes: [NSAttributedStringKey(rawValue: attributeName):"https"])
contentTf.attributedText = attStr
@objc func handleTap(sender: UITapGestureRecognizer) -> Void
let myTextView = sender.view as! UITextView
let layoutManager = myTextView.layoutManager
// location of tap in myTextView coordinates and taking the inset into account
var location = sender.location(in: myTextView)
location.x -= myTextView.textContainerInset.left;
location.y -= myTextView.textContainerInset.top;
// character index at tap location
let characterIndex = layoutManager.characterIndex(for: location, in: myTextView.textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
// if index is valid then do something.
if characterIndex < myTextView.textStorage.length
// print the character index
print("character index: (characterIndex)")
// print the character at the index
let myRange = NSRange(location: characterIndex, length: 1)
let substring = (myTextView.attributedText.string as NSString).substring(with: myRange)
print("character at index: (substring)")
// check if the tap location has a certain attribute
let attributeName = "CustomAttributeName"
let attributeValue = myTextView.attributedText.attribute(NSAttributedStringKey(rawValue: attributeName), at: characterIndex, effectiveRange: nil) as? String
if let value = attributeValue
print("You tapped on (attributeName) and the value is: (value)")
TEST
character index: 3
character at index: p
You tapped on CustomAttributeName and the value is: https
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
I did not know addGestureRecognizer is in TableViewCell now. thank you
– Adam
Aug 23 at 5:51