0

I have a UIlabel and it's text like following

label.text = "#fun #fun #google #youtube"

I want to make the UILabel clickable and open it's url.

I also make the dictionary to set it's keys&values.

var dic:[String:String] = ["https://www.yahoo.com.tw/"   :"fun",
                           "https://www.facebook.com.tw/":"fun",
                           "https://www.google.com.tw/"  :"Google",
                           "https://www.youtube.com/"    :"Youtube"
                          ]  
//How about change it's type to array?
var arr:[[String:String]] = [["https://www.yahoo.com.tw/"   :"fun"],
                             ["https://www.facebook.com.tw/":"fun"],
                             ["https://www.google.com.tw/"  :"Google"],
                             ["https://www.youtube.com/"    :"Youtube"]
                            ] 

How to seprate "fun" to load different url When I click "#fun"?

I use third-library ActiveLabel.swift to achieve UILabel clickable.

label.handleHashtagTap({ (string) in 
    //do something.

    let keys = self.dic.allKeys(forValue: "#\(string) ")        
    print("--> keys: \(keys)")

})

extension Dictionary where Value: Equatable {
    func allKeys(forValue val: Value) -> [Key] {
        return self.filter { $1 == val }.map { $0.0 }
    }
}
Beginnerrrrrr
  • 537
  • 1
  • 8
  • 27
  • 1
    Please show what you have tried so far. – Laffen Jan 17 '18 at 09:00
  • Sorry, but I don't have any idea to distinguish "#fun". – Beginnerrrrrr Jan 17 '18 at 09:04
  • If you use a `UITextField` you can get the info at which character the user tapped. – dasdom Jan 17 '18 at 09:14
  • You have already implemented the *clickable* functionality as I understand. So your question is now misleading. Edit the question title and ask as you need. – nayem Jan 17 '18 at 09:14
  • okay ,I update my question. – Beginnerrrrrr Jan 17 '18 at 09:20
  • Clearly, a `UITextview` with a little of modifications could pass for a `UILabel` and using `NSAttributedString` is could have quick implementation of what you want. If you still want to keep using `UILabel` (which aren't made for this), could you at least show the code of `handleHashtagTap()`, because the solution could be there too, and how is populated the label text with the dictionary/array with the urls? – Larme Jan 17 '18 at 09:26
  • `handleHashtagTap()` is the third-framework function. – Beginnerrrrrr Jan 17 '18 at 09:30
  • Returning just a `string` in the block, you can't guess which "fun" of `"#fun #fun #google #youtube"` has been tapped, first one, second one? Because it seems (I just read the Readme.md, not check the class for hidden feature) that it's built for "value = key" only. So as I suggested use a `UITextView` (it's built almost built for that), or find another third lib. – Larme Jan 17 '18 at 09:59
  • go to this https://github.com/TTTAttributedLabel/TTTAttributedLabel url there is library, my be it can help you. – sumit kumar Jan 17 '18 at 10:09
  • See this [answer](https://stackoverflow.com/a/28519273/7104617) – Alexey Kudlay Jan 17 '18 at 10:38

4 Answers4

3

Use array of dictionary and then do something like this

let dataArray = [["https://www.yahoo.com.tw/"   :"fun"],
                         ["https://www.facebook.com.tw/":"fun"],
                         ["https://www.google.com.tw/"  :"Google"],
                         ["https://www.youtube.com/"    :"Youtube"]
                        ] 

And you can run a for loop to show all the values on your label :

for i in 0..<dataArray.count{
    let label = UILabel()
    label.tag = i
    for (key,value) in dataArray[i]{
        print(key, value)
        label.text = "#\(value)"
    }
    // then add tap gesture to that label
}

You have to create labels dynamically and each label will have a tap gesture.

On tap gesture you can get the tag of the label and thus you can get the tapped value from your dataArray based on your tag.

Sharad Chauhan
  • 4,821
  • 2
  • 25
  • 50
0

You can use UICollectionView. Make Cells for all words. As you have 4 word Use 4 Cells And give UICollectionView Direction According to that Vertical or Horizontal. It also help you as Archive Great Layout and you can customise how you want.

jay patel
  • 238
  • 2
  • 14
0

You can achieve what you're describing by using an UITextView with a NSAttributedString containing tags with links.

You can look at the example below or copy/paste into a new playground using Xcode to test it.

You can also override the default URL interaction behavior of UITextView if you want to use the URL different than the default action.

//: A UIKit based Playground for presenting user interface

import UIKit
import PlaygroundSupport

class MyViewController : UIViewController, UITextViewDelegate {

    // Assign a webView to this to override the default url interaction from the tagView
    var webView: UIWebView?

    func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {

        // Check if a webView is set to be used to load URLs
        guard let webView = webView else {

            // Proceeds with default url interaction if no webview is assigned
            return true
        }

        // Load URL into the webview instead
        webView.loadRequest(URLRequest(url: URL))

        // Stops the default url interaction and uses the webView instead
        return false
    }

    override func loadView() {
        let view = UIView()
        view.backgroundColor = .white

        let tagView = UITextView()
        // Disable editing of the UITextView, this stops users from changing the UITextView content
        tagView.isEditable = false
        // Make self handle events raised by the tagView, this is required to receive the shouldInteractWith URL event
        tagView.delegate = self

        tagView.frame = CGRect(x: 100, y: 200, width: 200, height: 20)

        let dic:[String:String] = ["https://www.yahoo.com.tw/"   :"fun",
                                   "https://www.facebook.com.tw/":"fun",
                                   "https://www.google.com.tw/"  :"Google",
                                   "https://www.youtube.com/"    :"Youtube"
        ]

        let attributedString = NSMutableAttributedString()

        // Iterate through the dictionary containing tags with links
        // and create a NSAttributedString for every tag
        for (link, tag) in dic {

            // Skip tags that have a malformed link
            guard let url = URL(string: link) else { continue }

            // Create the NSAttributedString with the tag and link
            let tagString = NSAttributedString(string: "#\(tag) ", attributes: [NSAttributedStringKey.link: url])

            attributedString.append(tagString)
        }

        // Set the tags string to the tagView
        tagView.attributedText = attributedString

        view.addSubview(tagView)
        self.view = view
    }
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()
// Enjoy your tags with links

NSAttributedString - Apple Documentation

Laffen
  • 2,753
  • 17
  • 29
0

You can use NSAttributedString with documentType html. Please refer this example:

class ViewController: UIViewController, UITextViewDelegate {

    @IBOutlet weak var textView: UITextView!

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

        let attrText = htmlAttributedString("<span style=\"font-family: 'NotoSans'; font-size: 16; color: #666666\">ĐÃ CÀO TRÚNG <a href=\"google.com.vn\">Link here</a></span>")
        textView.delegate = self
        textView.isEditable = false
        textView.attributedText = attrText
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
        print(URL.absoluteString)
        return false
    }

    func htmlAttributedString(_ templateString: String) -> NSAttributedString? {
        do {
            if let data = templateString.data(using: .unicode, allowLossyConversion: true) {
                let options = [
                    NSAttributedString.DocumentReadingOptionKey.documentType: NSAttributedString.DocumentType.html,
                    ]
                let str = try NSAttributedString(data: data, options: options, documentAttributes: nil)
                return str
            }
        } catch let error {
            print(error.localizedDescription)
        }


        return nil
    }

}

With html documentType, you can freely to style your text. And also, to detect which url is clicked, you can use func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool delegate from UITextView

To remove delay on link click, you can also refer to this gist: https://gist.github.com/benjaminbojko/c92ac19fe4db3302bd28

dduyduong
  • 124
  • 1
  • 5