SwiftUI 3.0, iOS15부터는 Text(.init(보여줄_텍스트)) 라고만 쳐도
알아서 텍스트 내 link를 감지하고 클릭가능한 링크로 포맷팅해준다.
Text(.init("링크를 넣으면 www.google.com 클릭 가능해요. 여러개도 가능해요 https://naver.com"))
.padding(.horizontal, 14)
.padding(.vertical, 10)
.cornerRadius(12)
//...

근데 문제는 알아서 일을 너무 잘 한 나머지 바로 외부 브라우저로 url이 열린다.
사용자가 앱에서 이탈하는 것을 막기 위해서 inapp 브라우저로 띄우려고 또 한참 찾아본 결과!
iOS26부터 지원 되는 기능이 있다는 것을 알게 됐다..!! 굉장한 신규 기능!
요걸 해보려고 하니 맥북부터 업데이트를 해야해서리..ㅋㅋ 업데이트 눌러놓고 블로그 적기 시작함
뭐 막 UIKit이랑 연동하고 어쩌고 저쩌고 하는 방법도 있는 거 같지만
새 기능으로 훨씬 간단하게 되는 거 같아서 일단 26+ 이후로는 이걸로 구현 + 이전 버전은 그냥 외부 브라우저로 두기로 했다.
(결론이 궁금하면 아래로..!!)
환경변수에서 openURL 키값으로 설정된 OpenURLAction 인스턴스를 가져와서
함수처럼 실행하는 게 일단 기본이다.
Button과 사용 시 - iOS26 이전
아래 첫번째 예시(OpenURLExample)처럼
Button 을 눌러서 url을 열게 할 때 사용하면 된다.
@available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *)
extension EnvironmentValues {
/// An action that opens a URL.
///
/// Read this environment value to get an ``OpenURLAction``
/// instance for a given ``Environment``. Call the
/// instance to open a URL. You call the instance directly because it
/// defines a ``OpenURLAction/callAsFunction(_:)`` method that Swift
/// calls when you call the instance.
///
/// For example, you can open a web site when the user taps a button:
struct OpenURLExample: View {
@Environment(\.openURL) private var openURL //여기서 환경변수 데려와서
var body: some View {
Button {
if let url = URL(string: "https://www.example.com") {
openURL(url) //여기서 써먹으면 됨
}
} label: {
Label("Get Help", systemImage: "person.fill.questionmark")
}
}
}
/// If you want to know whether the action succeeds, add a completion
/// handler that takes a Boolean value. In this case, Swift implicitly
/// calls the ``OpenURLAction/callAsFunction(_:completion:)`` method
/// instead. That method calls your completion handler after it determines
/// whether it can open the URL, but possibly before it finishes opening
/// the URL. You can add a handler to the example above so that
/// it prints the outcome to the console:
///
/// openURL(url) { accepted in
/// print(accepted ? "Success" : "Failure")
/// }
///
/// The system provides a default open URL action with behavior
/// that depends on the contents of the URL. For example, the default
/// action opens a Universal Link in the associated app if possible,
/// or in the user’s default web browser if not.
Text와 사용 시 - iOS26 이전
Text로 쓸 때에는 이렇게 .environment로 직접 OpenURLAction을 변경해줄 수 있다.
내가 원하는대로 처리하고, return .handled 요렇게 반환해주면 된다.
/// You can also set a custom action using the ``View/environment(_:_:)``
/// view modifier. Any views that read the action from the environment,
/// including the built-in ``Link`` view and ``Text`` views with markdown
/// links, or links in attributed strings, use your action. Initialize an
/// action by calling the ``OpenURLAction/init(handler:)`` initializer with
/// a handler that takes a URL and returns an ``OpenURLAction/Result``:
Text("Visit [Example Company](https://www.example.com) for details.")
.environment(\.openURL, OpenURLAction { url in
handleURL(url) // Define this method to take appropriate action.
return .handled
})
/// SwiftUI translates the value that your custom action's handler
/// returns into an appropriate Boolean result for the action call.
/// For example, a view that uses the action declared above
/// receives `true` when calling the action, because the
/// handler always returns ``OpenURLAction/Result/handled``.
@MainActor @preconcurrency public var openURL: OpenURLAction
}
이때 return 값으로 handled, discarded, systemAction, systemAction(_ url: URL) 이 가능했다. (iOS15+ 까지는!)
systemAction으로 반환하면 기본 시스템 처리 액션이 진행돼서 외부 브라우저에서 url이 열리게 되는 구조다.
결론: iOS26+
Text와 사용 시 - iOS26 +
방금 말한 return 값에 이번에 요게 하나 더 추가됐다!
@available(iOS 26.0, macOS 26.0, tvOS 26.0, watchOS 26.0, *)
public static func systemAction(_ url: URL? = nil, prefersInApp: Bool) -> OpenURLAction.Result
그래서 아래와 같이 쓰면 인앱브라우저가 우선으로 열리게 된다!
Text(.init(message.text))
.environment(\.openURL, OpenURLAction { _ in
.systemAction(prefersInApp: true) //요렇게
})
근데 꼭 이렇게 하지 않아도, onOpenURL 함수를 이용해도 된다. 참고
Text(.init(message.text))
.onOpenURL(prefersInApp: true)
이렇게 하면 인앱브라우저에서 우선 열기 완성!
Button과 사용 시 - iOS26 +
버튼 예시로 돌아와서,
버튼에서도 마찬가지로 사용가능하다!
https://youtu.be/S1lGyjiExq4 에 나온 예시
struct ContentView: View {
@Environment(\.openURL) var openURL
var body: some View {
Button {
openURL(URL(string: "https://www.apple.com")!, prefersInapp: true) //이 부분
} label: {
Label("Go to Apple", systemImage: "applelogo")
}
}
}
참고:
https://www.reddit.com/r/SwiftUI/comments/1e6onsg/how_to_autodetect_links_in_a_string/
https://stackoverflow.com/questions/66813822/how-to-highlight-and-clickable-if-text-is-url-swiftui
https://fatbobman.com/en/posts/open_url_in_swiftui/
https://youtu.be/S1lGyjiExq4
https://developer.apple.com/documentation/swiftui/view/onopenurl(prefersinapp:)/
댓글