Skip to content

Instantly share code, notes, and snippets.

@CH3COOH
Created April 20, 2025 07:48
Show Gist options
  • Save CH3COOH/d038de1989906622a98e285d4e1231cf to your computer and use it in GitHub Desktop.
Save CH3COOH/d038de1989906622a98e285d4e1231cf to your computer and use it in GitHub Desktop.
SwiftUIの `@Environment(\.openURL)` を使って URLをアプリ内ブラウザで開く
//
// ContentView.swift
// SampleOpenUrl
//
// Created by KENJIWADA on 2025/04/20.
//
import SwiftUI
struct ContentView: View {
@Environment(\.openURL) private var openURL
private static let url = URL(string: "https://dev.classmethod.jp/author/wada-kenji/")!
var body: some View {
VStack(spacing: 24) {
Button(action: openSampleURL) {
VStack {
Text("Open Action")
}
}
Link("Open Link", destination: ContentView.url)
}
}
private func openSampleURL() {
openURL(ContentView.url)
}
}
#Preview {
ContentView()
}
//
// SafariSheetModifier.swift
// SampleOpenUrl
//
// Created by KENJIWADA on 2025/04/20.
//
import SafariServices
import SwiftUI
/// URL をシート表示用に Identifiable に適合させるためのラッパー構造体
/// - Note: sheet(item:) で使用するために必要
struct IdentifiableURL: Identifiable {
let id = UUID()
let url: URL
init(_ url: URL) {
self.url = url
}
}
private struct SafariView: UIViewControllerRepresentable {
let url: URL
func makeUIViewController(context _: Context) -> SFSafariViewController {
let vc = SFSafariViewController(url: url)
vc.dismissButtonStyle = .close
vc.preferredControlTintColor = .systemPink
return vc
}
func updateUIViewController(_: SFSafariViewController, context _: Context) {
// SFSafariViewControllerは内部状態を管理するため、更新は不要
}
}
struct SafariSheetModifier: ViewModifier {
@State private var identifiableURL: IdentifiableURL?
func body(content: Content) -> some View {
content
.environment(\.openURL, OpenURLAction { url in
// HTTP/HTTPS スキーム以外は標準の動作(ブラウザで開く等)にフォールバック
if url.scheme == "https" || url.scheme == "http" {
identifiableURL = IdentifiableURL(url)
return .handled
} else {
return .systemAction
}
})
.sheet(item: $identifiableURL) { identifiableURL in
SafariView(url: identifiableURL.url)
}
}
}
extension View {
/// View に Safari シート表示機能を追加する
/// アプリ内で開かれる URL を SFSafariViewController で表示するようにする
func safariSheet() -> some View {
modifier(SafariSheetModifier())
}
}
//
// SampleOpenUrlApp.swift
// SampleOpenUrl
//
// Created by KENJIWADA on 2025/04/20.
//
import SwiftUI
@main
struct SampleOpenUrlApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.safariSheet() // アプリ全体に Safari シート機能を適用
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment