You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI Widget点击拨打电话:锁屏可用且不启动APP的实现疑问

在SwiftUI Widget中实现锁屏下无主App启动的拨打电话功能

你不需要依赖私有API,苹果提供了公开的SiriKit INStartCallIntent 就能实现需求——这也是官方快捷指令Widget的实现方式。下面是具体实现步骤:

1. 配置项目权限

首先在Xcode中给主App和Widget Target添加SiriKit能力:

  • 选中项目Target → 切换到「Signing & Capabilities」标签 → 点击「+ Capability」
  • 搜索「SiriKit」并添加,勾选「Calls」选项
  • 在主App和Widget的Info.plist中添加NSUserActivityTypes数组,包含INStartCallIntent;同时添加NSMicrophoneUsageDescription(系统要求配置该权限描述,即使Widget拨打电话不需要麦克风)

2. 创建拨打电话的AppIntent

编写继承自AppIntent的结构体,在perform方法中调用INStartCallIntent:

import AppIntents
import Intents

struct CallPhoneIntent: AppIntent {
    static var title: LocalizedStringResource = "拨打电话"
    static var description = IntentDescription("直接拨打指定电话号码")
    
    @Parameter(title: "电话号码")
    var phoneNumber: String
    
    func perform() async throws -> some IntentResult {
        let callIntent = INStartCallIntent(
            contacts: nil,
            contactIdentifiers: nil,
            phoneNumber: phoneNumber,
            video: false
        )
        try await callIntent.execute()
        return .result()
    }
}

3. 在Widget中绑定Intent按钮

在Widget视图里,用.intent()修饰按钮,绑定上面创建的CallPhoneIntent:

struct CallWidgetEntryView: View {
    var entry: Provider.Entry
    
    var body: some View {
        Button(intent: CallPhoneIntent(phoneNumber: "10086")) {
            VStack {
                Image(systemName: "phone.fill")
                    .font(.largeTitle)
                Text("拨打客服")
                    .font(.caption)
            }
            .padding()
            .background(Color.blue)
            .foregroundColor(.white)
            .cornerRadius(12)
        }
    }
}

方案优势与说明

  • 无主App启动:INStartCallIntent直接由系统处理,不会唤起主App进程
  • 锁屏可用:只要用户未禁用Widget的锁屏显示权限,点击按钮就能正常触发拨号
  • 合规性:这是苹果公开API,不存在审核风险

之前方案失败的原因

  • .widgetURL的设计初衷就是通过URL跳转主App,必然会启动主App
  • App Extension进程受沙箱限制,无法访问UIApplication.shared
  • openURL环境变量不满足AppIntent的Sendable协议要求,无法在Intent中使用

注意事项

  • 该方案要求iOS 17及以上版本,因为INIntent.execute()是iOS 17新增的异步方法
  • 用户首次点击时会弹出Siri权限请求,需用户允许后才能正常使用

内容的提问来源于stack exchange,提问作者Mark

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 14:46:17