iOS 小组件开发第九篇:在 iOS 17 上创建可交互的小组件

这里每天分享一个 iOS 的新知识,快来关注我吧

前言

小组件相关内容传送门:

iOS 小组件开发第一篇:基础介绍
iOS 小组件开发第二篇:时间线
iOS 小组件开发第三篇:实战
iOS 小组件开发第四篇:小组件的尺寸
iOS 小组件开发第五篇:开发可配置的小组件
iOS 小组件开发第六篇:点击事件和交互
iOS 小组件开发第七篇:锁屏小组件
iOS 小组件开发第八篇:灵动岛开发

今天继续讲小组件,在今年的 iOS 17 中,苹果对小组件的能力进一步升级,目前终于可以在不打开 App 的情况下进行交互了,今天就带大家一起实现这个新功能。

创建

首先还是先创建一个 Widget Target

AppIntent

要想实现可点击的按钮需要先自定义一个 AppIntent,比如我们要实现一个计数器的功能,可以这样实现一个 AppIntent

首先导入 import AppIntents,然后实现以下代码:

swift 复制代码
struct CalculateIntent: AppIntent {
    
    static var title: LocalizedStringResource = "Calculate Task"
    static var description: IntentDescription = IntentDescription("Calculate Number Task")
    
    @Parameter(title: "value")
    var value: Int
    
    init() { }
    init(value: Int) {
        self.value = value
    }
    
    func perform() async throws -> some IntentResult {
        NumberManager.number += value
        return .result()
    }
}

解释一下代码,我们实现一个名为 CalculateIntent 的结构体,遵守 AppIntent 协议,然后实现协议内容:titledescription,然后添加一个 value 属性,Int 类型,用来存储传入的数字,最后实现 perform() 方法。

最终这个 CalculateIntent 会用在我们可交互的按钮上,当点击按钮的时候会调用 perform() 方法。

除此之外,我们还需要一个全局属性存储计算的结果:

csharp 复制代码
struct NumberManager {
    static var number = 0
}

当我们执行完运算,return .result() 的时候,系统会自动调用刷新操作,此时会刷新小组件的时间线。

Widegt 代码部分

有了 CalculateIntent 结构体就可以来构建可交互的按钮了,Button 组件 和 Toggle 组件在 iOS 17 上新增了支持传入 AppIntent 协议的初始化方法:

swift 复制代码
@available(iOS 17.0, macOS 13.0, tvOS 17.0, watchOS 10.0, *)
extension Button {

    /// Creates a button that performs an `AppIntent`.
    ///
    /// - Parameters:
    ///   - intent: The `AppIntent` to execute.
    ///   - label: A view that describes the purpose of the button's `action`.
    public init<I>(intent: I, @ViewBuilder label: () -> Label) where I : AppIntent
}

@available(iOS 17.0, macOS 13.0, tvOS 17.0, watchOS 10.0, *)
extension Toggle {

    /// Creates a toggle performing an `AppIntent`.
    ///
    /// - Parameters:
    ///   - isOn: Whether the toggle is on or off.
    ///   - intent: The `AppIntent` to be performed.
    ///   - label: A view that describes the purpose of the toggle.
    public init<I>(isOn: Bool, intent: I, @ViewBuilder label: () -> Label) where I : AppIntent
}

利用这个方法可以创建出可交互的 Button,我们在页面上创建几个用来点击计算的按钮,另外再创建一个展示最终结果的 Text 组件:

less 复制代码
struct InteractivityWidgetEntryView : View {
    var entry: Provider.Entry

    var body: some View {
        VStack {
            Text("结果: \(NumberManager.number)")
            
            HStack {
                Button(intent: CalculateIntent(value: 10)) {
                    Text("加 10")
                }
                Button(intent: CalculateIntent(value: 1)) {
                    Text("加 1")
                }
                Button(intent: CalculateIntent(value: -1)) {
                    Text("减 1")
                }
                Button(intent: CalculateIntent(value: -10)) {
                    Text("减 10")
                }
            }
        }
    }
}

最后看下效果:

当点击下边几个按钮时,会执行数字计算,最后显示在上边的 Text 中。

最后

需要注意,可交互的组件仅支持 ButtonToggle 组件,其他控件都不起作用。

另外,因为 AppIntent 执行结束后,会导致小组件重新加载时间线,这就会带来从操作到 UI 结果展示之间有一小段延迟,Apple 也提供了一个方式避免这种问题,可以使用 .invalidatableContent() 修饰符来修饰某个视图,这样在点击按钮之后到 UI 更新之前,更新内容都是无效的。

这里每天分享一个 iOS 的新知识,快来关注我吧

本文同步自微信公众号 "iOS新知",每天准时分享一个新知识,这里只是同步,想要及时学到就来关注我吧!

相关推荐
_阿南_1 天前
flutter在Xcode26打包的iOS26上全屏支持右滑的问题
flutter·ios·xcode
2501_916007471 天前
iOS 26 软件性能测试 新版系统下评估全流程 + 多工具辅助方案
android·macos·ios·小程序·uni-app·cocoa·iphone
00后程序员张1 天前
Swoole HTTPS 实战,在生产环境部署、性能权衡与排查流程
后端·ios·小程序·https·uni-app·iphone·swoole
2501_915909061 天前
iOS App 上架全流程详解:证书配置、打包上传、审核技巧与跨平台上架工具 开心上架 实践
android·ios·小程序·https·uni-app·iphone·webview
2501_915106321 天前
iOS 26 系统流畅度测试实战分享,多工具组合辅助策略
android·macos·ios·小程序·uni-app·cocoa·iphone
2501_915918411 天前
开发 iOS 应用全流程指南,环境搭建、证书配置与跨平台使用 开心上架 上架AppStore
android·ios·小程序·https·uni-app·iphone·webview
方君宇1 天前
iOS App小组件(Widget)显示LottieFiles动画和GIF图片
ios
Digitally1 天前
如何将 iPhone 联系人同步到 Mac
macos·ios·iphone
Digitally1 天前
无需 iCloud 在 iPhone 之间传输文本消息
ios·iphone·icloud
2501_915921432 天前
iOS 是开源的吗?苹果系统的封闭与开放边界全解析(含开发与开心上架(Appuploader)实战)
android·ios·小程序·uni-app·开源·iphone·webview