How to Create a "Hyperlink" with Swift

How can I create a hyperlink with Swift?

The One approach would be something like the following.

The assumptions are:

  • self.urls is a string array containing the urls associated with each UILabel.
  • Each UILabel tag has been set to the corresponding index in the array
  • labelTapped: is set as the touchUpInside handler for the labels.
import Foundation
import UIKit

class urltest {

var urls:[String]

init() {
self.urls=[String]() // Load URLs into here
}

@IBAction func labelTapped(sender:UILabel!) {

let urlIndex=sender.tag;
if (urlIndex >= 0 && urlIndex < self.urls.count) {
self.openUrl(self.urls[urlIndex]);
}

}

func openUrl(url:String!) {

let targetURL=NSURL.URLWithString(url)

let application=UIApplication.sharedApplication()

application.openURL(targetURL);

}
}

How to add hyperlink with a title in ios app using swift?

You can try using a attributed string within a textfield and add it within the UIAlertView.

Step 1: Create a extension of attributed string to find the link and add appropriate style for the link text.

extension NSMutableAttributedString {

public func SetAsLink(textToFind:String, linkURL:String) {

let foundRange = self.mutableString.range(of: textToFind)
if foundRange.location != NSNotFound {
self.addAttribute(.link, value: linkURL, range: foundRange)
}
}
}

Step 2: Create a attributed string and add the style to it.

let attributedString = NSMutableAttributedString(string:"Please Open this LINK!")
attributedString.SetAsLink(textToFind: "LINK", linkURL: "http://stackoverflow.com")

Step 3: Create the alert view

let alert: UIAlertView = UIAlertView(title: "Title", message: "message",
delegate: self, cancelButtonTitle: "OK", otherButtonTitles: "Cancel")

Step 4: Create a un-editable text field

 let Txt:UITextView = UITextView(frame:CGRect(x: 0, y: 0, width: 100, height: 100))

Step 5 : Set attributed string to the text field

Txt.attributedText = attributedString;

Step 6: Make the txt field un-editable and detect link type

Txt.isEditable=false;
Txt.dataDetectorTypes = UIDataDetectorTypes.link;

Step 7: Set the text field to the alert and show the alert

     Txt.isEditable=false;
Txt.dataDetectorTypes = UIDataDetectorTypes.link;

To summarise it

To show the alert :

let attributedString = NSMutableAttributedString(string:"Please Open this LINK!")
attributedString.SetAsLink(textToFind: "LINK", linkURL: "http://stackoverflow.com")

let alert: UIAlertView = UIAlertView(title: "Title", message: "message",
delegate: self, cancelButtonTitle: "OK", otherButtonTitles: "Cancel")

let Txt:UITextView = UITextView(frame:CGRect(x: 0, y: 0, width: 100, height: 100))
Txt.attributedText = attributedString;
Txt.isEditable=false;
Txt.dataDetectorTypes = UIDataDetectorTypes.link;

alert.setValue(Txt, forKey: "accessoryView")
alert.show()

Extending the attributed string

extension NSMutableAttributedString {

public func SetAsLink(textToFind:String, linkURL:String) {

let foundRange = self.mutableString.range(of: textToFind)
if foundRange.location != NSNotFound {
self.addAttribute(.link, value: linkURL, range: foundRange)
}
}
}

P.S : Don't forget to make your view controller the UIAlertViewDelegate.

Here is the sample project

If you are using CDAlertView you can try this:

let alert = CDAlertView(title: "Awesome Title", message: "Are you in?!", type: .notification)
let doneAction = CDAlertViewAction(title: "Sure! )
alert.add(action: doneAction)
let nevermindAction = CDAlertViewAction(title: "Nevermind )
alert.add(action: nevermindAction)

let myCustomView = UIVIew(frame: CGRectMake(0,0,280,200))
let Txt:UITextView = UITextView(frame:CGRect(x: 0, y: 0, width: 100, height: 100))
Txt.attributedText = attributedString;
Txt.isEditable=false;
Txt.dataDetectorTypes = UIDataDetectorTypes.link;
myCustomView.addSubview(Txt)
alert.customView = myCustomView
alert.show()

How to make hyperlinks in SwiftUI

Motjaba Hosseni is right so far there is nothing that resembles NSAttributedString in SwiftUI.
This should solve your problem for the time being:

import SwiftUI

struct ContentView: View {
var body: some View {
VStack {
Text("By tapping Done, you agree to the ")
HStack(spacing: 0) {
Button("privacy policy") {}
Text(" and ")
Button("terms of service") {}
Text(".")
}
}
}
}

SwiftUI Text - how can I create a hyperlink and underline a weblink in a string

This was the final solution I used. Should work for a variety of string inputs.

import SwiftUI

struct HyperlinkAndUnderlineTextView: View {

var body: some View {

ScrollView {

VStack (alignment: .leading, spacing: 30) {

Group {
CustomTextWithHyperlinkAndUnderline("Test of a hyperlink www.google.co.uk within a text message", .blue)
CustomTextWithHyperlinkAndUnderline("www.google.co.uk hyperlink at the start of a text message", .blue)
CustomTextWithHyperlinkAndUnderline("Test of hyperlink at the end of a text message www.google.co.uk", .blue)
CustomTextWithHyperlinkAndUnderline("www.google.co.uk", .blue)
CustomTextWithHyperlinkAndUnderline("This is 1 hyperlink www.google.co.uk. This is a 2nd hyperlink www.apple.com", .blue)
CustomTextWithHyperlinkAndUnderline("This is 1 hyperlink www.google.co.uk. This is a 2nd hyperlink www.apple.com. This is text after it.", .blue)
CustomTextWithHyperlinkAndUnderline("This is 1 hyperlink www.google.co.uk. This is a 2nd hyperlink www.apple.com. This is a 3rd hyperlink www.microsoft.com", .blue)
CustomTextWithHyperlinkAndUnderline("This is 1 hyperlink www.google.co.uk. This is a 2nd hyperlink www.apple.com. This is a 3rd hyperlink www.microsoft.com. This is text after it.", .blue)
CustomTextWithHyperlinkAndUnderline("www.google.co.uk is a hyperlink at the start of a text message. www.apple.com is the 2nd hyperlink within the same text message.", .blue)
CustomTextWithHyperlinkAndUnderline("This is a test of another type of url which will get processed google.co.uk", .blue)
}

Group {
CustomTextWithHyperlinkAndUnderline("google.co.uk", .blue)
CustomTextWithHyperlinkAndUnderline("Pure text with no hyperlink", .blue)
CustomTextWithHyperlinkAndUnderline("Emoji test quot;, .blue)
}
}
}
}
}

struct SplitMessageContentWithType {
var content: String = ""
var type: contentType = .text
}

enum contentType {
case text
case url
}

//Function to produce a text view where all urls and clickable and underlined
func CustomTextWithHyperlinkAndUnderline(_ inputString: String, _ underlineColor: Color) -> Text {

let inputText: [SplitMessageContentWithType] = splitMessage(inputString)


var output = Text("")

for input in inputText {
let text: Text

text = Text(.init(input.content))
.underline(input.type == .url ? true : false, color: underlineColor)

output = output + text
}

return output

}

func splitMessage(_ inputString: String) -> [SplitMessageContentWithType] {


//1) Function to detect if the input string contains any urls and returns the ones found as an array of strings
func detectIfInputStringContainsUrl(inputString: String) -> [String] {

let urlDetector = try! NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue)
let matches = urlDetector.matches(in: inputString, options: [], range: NSRange(location: 0, length: inputString.utf16.count))

var urls: [String] = []

for match in matches {
guard let range = Range(match.range, in: inputString) else { continue }
let url = inputString[range]

urls.append(String(url))
}
return urls

}
let urlsFoundInInputString = detectIfInputStringContainsUrl(inputString: inputString)
print("\n \nurlsFoundInInputString are: \(urlsFoundInInputString)")



//2) Function to get the string components either side of a url from the inputString. Returns these components as an array of strings
func getStringComponentsSurroundingUrls(urlsFoundInInputString: [String]) -> [String] {

var stringComponentsSurroundingUrls: [String] = []

for (index, url) in urlsFoundInInputString.enumerated() {

let splitInputString = inputString.components(separatedBy: url)

//This code handles the case of an input string with 2 hyperlinks inside it (e.g. This is 1 hyperlink www.google.co.uk. This is a 2nd hyperlink www.apple.com. This is text after it.)
//In the 1st pass of the for loop, this will return splitInputString = ["This is 1 hyperlink ", ". This is a 2nd hyperlink www.apple.com. This is text after it."]
//Because the last element in the array contains either "www" or "http", we only append the contents of the first (prefix(1)) to stringComponentsSurroundingUrls (i.e "This is 1 hyperlink ")
//In the 2nd pass of the for loop, this will return splitInputString = ["This is 1 hyperlink www.google.co.uk. This is a 2nd hyperlink ", ". This is text after it."]
//Beacuse the last element in the array does not contain a hyperlink, we append both elements to stringComponentsSurroundingUrls
if splitInputString.last!.contains("www") || splitInputString.last!.contains("http") {
stringComponentsSurroundingUrls.append(contentsOf: inputString.components(separatedBy: url).prefix(1))
} else {
stringComponentsSurroundingUrls.append(contentsOf: inputString.components(separatedBy: url))
}


//At this point in the code, in the above example, stringComponentsSurroundingUrls = ["This is 1 hyperlink ",
// "This is 1 hyperlink www.google.co.uk. This is a 2nd hyperlink ",
// ". This is text after it."]
//We now iterate through this array of string, to complete another split. This time we separate out by any elements by urlsFoundInInputString[index-1]
//At the end of this for loop, stringComponentsSurroundingUrls = ["This is 1 hyperlink ",
// ". This is a 2nd hyperlink ",
// ". This is text after it."]
if index == urlsFoundInInputString.count - 1 {
for (index, stringComponent) in stringComponentsSurroundingUrls.enumerated() {
if index != 0 {
let stringComponentFurtherSeparated = stringComponent.components(separatedBy: urlsFoundInInputString[index-1])
stringComponentsSurroundingUrls.remove(at: index)
stringComponentsSurroundingUrls.insert(stringComponentFurtherSeparated.last!, at: index)
}
}
}
}

return stringComponentsSurroundingUrls
}

var stringComponentsSurroundingUrls: [String]
//If there no no urls found in the inputString, simply set stringComponentsSurroundingUrls equal to the input string as an array, else call the function to find the string comoponents surrounding the Urls found
if urlsFoundInInputString == [] {
stringComponentsSurroundingUrls = [inputString]
} else {
stringComponentsSurroundingUrls = getStringComponentsSurroundingUrls(urlsFoundInInputString: urlsFoundInInputString)
}
print("\n \nstringComponentsSurroundingUrls are: \(stringComponentsSurroundingUrls)")




//3)Function to markdown the urls found to follow a format of [placeholderText](hyperlink) such as [Google](https://google.com) so SwiftUI markdown can render it as a hyperlink
func markdown(urlsFoundInInputString: [String]) -> [String] {

var markdownUrlsArray: [String] = []

for url in urlsFoundInInputString {
let placeholderText = "[\(url)]"

var hyperlink: String
if url.hasPrefix("https://www.") {
hyperlink = "(\(url.replacingOccurrences(of: "https://www.", with: "https://")))"
} else if url.hasPrefix("www.") {
hyperlink = "(\(url.replacingOccurrences(of: "www.", with: "https://")))"
} else {
hyperlink = "(http://\(url))"
}

let markdownUrl = placeholderText + hyperlink

markdownUrlsArray.append(markdownUrl)
}

return markdownUrlsArray

}

let markdownUrls = markdown(urlsFoundInInputString: urlsFoundInInputString)
print("\n \nmarkdownUrls is: \(markdownUrls)")



//4) Function to combine stringComponentsSurroundingUrls and markdownUrls back together
func recombineStringComponentsAndMarkdownUrls(stringComponentsSurroundingUrls: [String], markdownUrls: [String]) -> [SplitMessageContentWithType] {

var text = SplitMessageContentWithType()
var text2 = SplitMessageContentWithType()
var splitMessageContentWithTypeAsArray: [SplitMessageContentWithType] = []

//Saves each string component and url as either .text or .url type so in the CustomTextWithHyperlinkAndUnderline() function, we can underline all .url types
for (index, stringComponents) in stringComponentsSurroundingUrls.enumerated() {
text.content = stringComponents
text.type = .text
splitMessageContentWithTypeAsArray.append(text)

if index <= (markdownUrls.count - 1) {
text2.content = markdownUrls[index]
text2.type = .url
splitMessageContentWithTypeAsArray.append(text2)
}
}

return splitMessageContentWithTypeAsArray
}


let recombineStringComponentsAndMarkdownUrls = recombineStringComponentsAndMarkdownUrls(stringComponentsSurroundingUrls: stringComponentsSurroundingUrls, markdownUrls: markdownUrls)
print("\n \nrecombineStringComponentsAndMarkdownUrls is: \(recombineStringComponentsAndMarkdownUrls)")

return recombineStringComponentsAndMarkdownUrls

}

UITextView with hyperlink text

Set isEditable = false or the text view will go into text-editing mode when user taps on it.

Swift 4 and later

let attributedString = NSMutableAttributedString(string: "Just click here to register")
let url = URL(string: "https://www.apple.com")!

// Set the 'click here' substring to be the link
attributedString.setAttributes([.link: url], range: NSMakeRange(5, 10))

self.textView.attributedText = attributedString
self.textView.isUserInteractionEnabled = true
self.textView.isEditable = false

// Set how links should appear: blue and underlined
self.textView.linkTextAttributes = [
.foregroundColor: UIColor.blue,
.underlineStyle: NSUnderlineStyle.single.rawValue
]

How do I add a link to a UILabel in swift?

Two ways to do it.

  1. Tap gesture - UITapGestureRecognizer
// considering you have a UILabel is added to your screen and you have formatted the label to look like a link.
let labelTap = UITapGestureRecognizer(target: self, action: #selector(self.linkLabelTapped(_:)))
self.linkLabel.isUserInteractionEnabled = true
self.linkLabel.addGestureRecognizer(labelTap)

@objc func linkLabelTapped(_ sender: UITapGestureRecognizer) {
print("linkLabelTapped")
}

  1. Don't use UILabel but UITextView with link recognition which gives you the formatting by default.
linkTextView.userInteractionEnabled = true
linkTextView.selectable = true
linkTextView.dataDetectorTypes = .Link
linkTextView.text = "https://www.google.com."

SwiftUI macOS - Create clickable hyperlink

Here is possible solution. Tested with Xcode 11.4 / macOS 10.15.4

demo

Button(action: {
// link action here
}) {
Text("www.stackoverflow.com").underline()
.foregroundColor(Color.blue)
}.buttonStyle(PlainButtonStyle())
.onHover { inside in
if inside {
NSCursor.pointingHand.push()
} else {
NSCursor.pop()
}
}


Related Topics



Leave a reply



Submit