跳转至
Structure

Link

A button that opens a URL

Declaration

struct Link<Label> : View where Label : View

Overview

A Link opens a URL when the user clicks. There are three initializers:

For example:

struct ExampleView: View {
    let urlString = "https://swiftontap.com"

    var body: some View {
        Group {
            if let url = URL(string: urlString) {
                // Creates a Link
                Link("View SwiftOnTap", destination: url)
            }
        }
    }
}
A gif displaying a view containing a static string variable set to the SwiftOnTap url and a Group with an if statement creating a link from the url string and a link "View SwiftOnTap" that brings the user to the SwiftOnTap website once clicked.

struct ExampleView: View {
    let url: String = "https://swiftontap.com"

    var body: some View {
        Group {
            if let url = URL(string: url) {
                Link(destination: url) {
                    RoundedRectangle(cornerRadius: 10)
                        .fill(Color.pink)
                        .padding()
                }
            }
        }
    }
}
A gif displaying a view containing a static string variable set to the SwiftOnTap url and a Group with an if statement creating a link from the url string and a link that brings the user to the SwiftOnTap website once clicked in the form of a pink filled rounded rectangle with padding.

Before Link was added to SwiftUI, there was no equivalent of a hyperlink outside of a WKWebView.

It was possible to create a button with blue text that opens a URL, but this requires the logic to be added manually each time. For example:

struct ContentView: View {
    let urlString = "https://swiftontap.com"

    var body: some View {
        if URL(string: urlString) != nil {

            //The old way to create a Link-style Button
            Button("Read more") {
                if let url = URL(string: urlString) {
                    UIApplication.shared.open(url, options: [:], completionHandler: {\_ in })
                }
            }
        } else {
            EmptyView()
                .onAppear { assertionFailure("URL was nil") }
        }
    }
}
In iOS 14 there is the option of Link, which does the action part of the Button above for us. Apple’s documentation unsafely unwraps a URL using the ‘!’ operator, but this is bad practice. You may know that this particular URL is created successfully because it links to example.com/TOS.html, a site owned by the Internet Assigned Numbers Authority (IANA) that convert URLs to IP addresses. But it's a mistake to assume that a URL string is valid and force unwrap the optional.

This example is held back by the lack of optional binding (if let or guard let) in the first version of SwiftUI, as it is instead restricted to comparing the URL to nil to ensure it exists. When this comparison confirms that the URL is not nil, this still doesn’t mean I can use it in the Button without unwrapping it first. This is why there is a slightly confusing additional step in the Button action, which optionally binds the URL to ensure that it is not nil.

The assertionFailure could have been in an else statement after the if let in the Button action, but the EmptyView has been added for consistency with the above Link example. An else statement containing EmptyView is not required, as any if statement around the only occupant of a ViewBuilder closure will return EmptyView when the if condition is false. If the URL was nil the user would see nothing, but an assertion would be triggered for the developer in debug mode.

This would allow us to be aware that the URL was nil, but without causing a crash for the end-user.

With updates to SwiftUI, the old code would roughly translate to the code below:

struct ExampleView: View {
    let urlString = "https://swiftontap.com"

    var body: some View {
        Group {
            if let url = URL(string: urlString) {

                // The new way to create a Link
                Link("View SwiftOnTap", destination: url)
            }
        }
    }
}
A gif displaying a view containing a static string variable set to the SwiftOnTap url and a Group with an if statement creating a link from the url string and a link "View SwiftOnTap" that brings the user to the SwiftOnTap website once clicked.

Now that SwiftUI supports if let, it is possible to directly create properties like the URL and create Views that use that data. Just as before, the link is only shown when the URL can be created, but it is not necessary to do multiple checks just to make sure that this is the case.

Availability

iOS 14.0+

macOS 11.0+

tvOS 14.0+

watchOS 7.0+

Topics


Type Alias

Body The type of view representing the body of this view.


Instance Property

body The content and behavior of the view.


Initializer

init(_:destination:) A Link initializer that opens a link when a title conforming to StringProtocol is clicked.

init(_:destination:) A Link initializer that opens a link when text is clicked.

init(destination:label:) A Link initializer that opens a link when a view is clicked.