SwiftUI打开网页SFSafariViewController
SwiftUI打开网页SFSafariViewController

SwiftUI打开网页SFSafariViewController

SFSafariViewController 是苹果在 iOS 9 引入的一个类,全名是 Safari Services Framework 的 SFSafariViewController。

它的作用是:在 App 内打开网页内容,但由系统 Safari 来渲染和管理。

苹果官方的定义:

“A view controller for displaying web content in your app, using Safari’s web engine.”

可以简单的理解为,相比WKWebView更简单、更安全。相比直接跳转到Safari更流畅、不会打断用户体验。

使用方式

在SwiftUI中需要封装SafariView组件:

import SwiftUI
import SafariServices

struct SafariView: UIViewControllerRepresentable {
    let url: URL
    
    func makeUIViewController(context: Context) -> SFSafariViewController {
        SFSafariViewController(url: url)
    }
    
    func updateUIViewController(_ vc: SFSafariViewController, context: Context) {}
}

SwiftUI使用sheet打开网页:

@State private var showSafari = false

Button("打开网页") {
    showSafari = true
}
.sheet(isPresented: $showSafari) {
    SafariView(url: URL(string: "https://www.fangjunyu.com")!)
        .presentationDetents([.medium, .large]) // iOS 16+ 可选高度
        .presentationCornerRadius(20)
}

主要特点

1、网页在独立的进程中运行,隔离你的 App,不会泄露 Cookie。

2、自带导航栏、加载进度条、分享菜单。

3、Safari样式:外观、手势、字体与 Safari 完全一致。

4、自动管理 Cookie:与系统 Safari 共用登录状态(比如登录过 Twitter / Gmail)。

5、可定制性有限:不能随意修改网页内容或注入 JS。

6、不能拦截链接:如果要完全自定义网页行为,必须用 WKWebView。

可自定义属性

需要创建更复杂的SafariView视图,定义阅读模式、背景色颜色等内容。

import SwiftUI
import SafariServices

struct SafariView: UIViewControllerRepresentable {
    let url: URL
    let entersReaderIfAvailable: Bool
    let barTintColor: UIColor?
    let controlTintColor: UIColor?
    let barCollapsingEnabled: Bool

    func makeUIViewController(context: Context) -> SFSafariViewController {
        // 创建 Configuration
        let config = SFSafariViewController.Configuration()
        config.entersReaderIfAvailable = entersReaderIfAvailable
        config.barCollapsingEnabled = barCollapsingEnabled

        // 创建 Safari 控制器
        let safariVC = SFSafariViewController(url: url, configuration: config)

        // 设置外观
        if let barColor = barTintColor {
            safariVC.preferredBarTintColor = barColor
        }
        if let controlColor = controlTintColor {
            safariVC.preferredControlTintColor = controlColor
        }

        return safariVC
    }

    func updateUIViewController(_ uiViewController: SFSafariViewController, context: Context) {
        // SafariViewController 的配置在创建后不能修改太多
        // 所以这里一般不做修改
    }
}

在SwiftUI中使用:

struct ContentView: View {
    @State private var showSafari = false

    var body: some View {
        Button("打开网页") {
            showSafari = true
        }
        .sheet(isPresented: $showSafari) {
            SafariView(
                url: URL(string: "https://www.fangjunyu.com")!,
                entersReaderIfAvailable: true,
                barTintColor: .systemBackground,
                controlTintColor: .systemBlue,
                barCollapsingEnabled: true
            )
            .presentationDetents([.medium, .large])  // iOS 16+ 可选高度
            .presentationDragIndicator(.visible)
        }
    }
}

可以微调颜色、行为、是否支持阅读模式等,但不能改变UI。

entersReaderIfAvailable → 自动进入阅读模式(如果网页支持)。

barCollapsingEnabled → 滚动网页时隐藏顶部工具栏。

preferredBarTintColor → 导航栏背景色。

preferredControlTintColor → 按钮颜色(关闭、分享按钮)。

这些属性都必须在控制器创建时设置,之后再修改通常不起作用。

SwiftUI 只是包装和弹出它,不会自己提供属性修改接口。

对比同类网页打开方式

1、openURL:跳转到Safari,不支持定制,会离开当前App;

2、Link:最简单,内部通过openURL实现;

3、SFSafariViewController:Safari内嵌视图,定制样式少,不离开当前App;

4、WKWebView:自定义网页容器,定制样式丰富,不离开当前App。

总结

SFSafariViewController可以在App内使用Safari打开网页,保留了Safari的安全与性能,也提供了App的连贯体验。

在SwiftUI中SFSafariViewController模版保留底部的安全区域(造成底部是透明的效果),可以使用ignoresSafeArea()忽略安全区域,让视图最大化。

SafariView(url: URL(string: "https://fangjunyu.com/2024/06/03/%e5%ad%98%e9%92%b1%e7%8c%aa%e7%8c%aa-%e4%bd%bf%e7%94%a8%e6%9d%a1%e6%ac%be/")!, entersReaderIfAvailable: true)
    .ignoresSafeArea()

相关文章

1、SwiftUI超链接Link:https://fangjunyu.com/2024/12/31/swift%e5%ba%94%e7%94%a8%e5%86%85%e5%88%9b%e5%bb%ba%e8%b6%85%e9%93%be%e6%8e%a5%e7%9a%84link%e6%96%b9%e6%b3%95/

2、SwiftUI打开链接openURL:https://fangjunyu.com/2025/11/07/swiftui%e6%89%93%e5%bc%80%e9%93%be%e6%8e%a5openurl/

3、SwiftUI WKWebView网页视图:https://fangjunyu.com/2025/11/07/swiftui-wkwebview%e7%bd%91%e9%a1%b5%e8%a7%86%e5%9b%be/

扩展知识

1、配置参数

在较新的iOS版本中,SFSafariViewController.Configuration添加了UI功能扩展和广告点击追踪归因。

1、activityButton(iOS 15+)

这是一个可自定义按钮,出现在 Safari 页面右上角(通常是“分享”按钮旁边)。

允许开发者为 Safari 页面添加一个额外的交互入口。

比如:“在 App 中打开” 、“收藏” 、“举报” 等按钮。

@available(iOS 15.0, *)
@NSCopying open var activityButton: SFSafariViewController.ActivityButton?

使用方法:

创建一个自定义按钮实例,然后赋值给配置。

if #available(iOS 15.0, *) {
    let config = SFSafariViewController.Configuration()
    
    let image = UIImage(systemName: "star.fill")!
    let button = SFSafariViewController.ActivityButton(templateImage: image, extensionIdentifier: nil)
    config.activityButton = button
}

这个按钮默认只会调用 Safari 自己的活动菜单逻辑(例如呼出分享菜单或扩展)。

如果希望有特定行为(比如回调),就需要结合 Safari Web Extension 或 Universal Links,让用户回到 App。

注意:

1)按钮图标必须是模板图像(单色可变色的 UIImage)。

2)不支持添加多个按钮。

3)点击行为会受限于系统安全策略,不能直接调用 App 内代码。

2、eventAttribution(iOS 15.2+)

这是一个与广告点击追踪(Ad Click Attribution) 有关的属性。

主要用于网页来源追踪,比如用户从广告点击进入网页时。

在展示 SFSafariViewController 时,将广告点击的来源信息传递进去,帮助系统在不泄露隐私的前提下进行事件归因(Attribution)。

这属于 Apple 的隐私保护广告机制(Private Click Measurement)。

@available(iOS 15.2, *)
@NSCopying open var eventAttribution: UIEventAttribution?

使用方法:

如果有广告点击事件,可以这样配置:

if #available(iOS 15.2, *) {
    let attribution = UIEventAttribution(sourceIdentifier: "com.example.ad",
                                         destinationURL: URL(string: "https://example.com")!,
                                         sourceDescription: "Ad Campaign 123",
                                         purchaser: nil)
    config.eventAttribution = attribution
}

系统会将此信息用于隐私保护的统计归因,不会暴露用户身份。

这主要针对广告或带追踪来源的场景(例如点击 App 内广告后打开网页)。

   

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开发者。

欢迎加入我们的 微信交流群QQ交流群,交流更多精彩内容!
微信交流群二维码 QQ交流群二维码

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注