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

如何实现类似SwitchBot的iOS小组件:点击切换状态后自动复原

如何实现类似SwitchBot的iOS小组件:点击切换状态后自动复原

嘿,刚好我之前做过类似的小组件需求,给你唠唠具体怎么实现,思路和代码都给你捋清楚!

首先核心逻辑就是点击触发动作→临时切换UI状态→等待几秒→自动复原UI,结合你已经在用的AppIntent和Button,咱们一步步来:

1. 先搞定状态的临时存储

因为小组件和主App是分开的进程,所以得用App Group共享的UserDefaults来存临时状态(记得先在Xcode里配置好App Group哦)。这个临时状态用来标记当前是否在执行动作,方便UI切换。

2. 编写AppIntent的执行逻辑

在你的perform()方法里,要做这几件事:

  • 先把临时状态设为true,告诉小组件“现在要执行动作啦”
  • 调用你的网络接口去控制SwitchBot场景
  • 等接口返回结果后,再等2秒(模拟SwitchBot的复原延迟)
  • 把临时状态清掉,再刷新小组件让UI复原

给你贴个示例代码:

struct ControlSwitchBotSceneIntent: AppIntent {
    static var title: LocalizedStringResource = "触发场景"
    
    func perform() async throws -> some IntentResult & UpdatesWidget {
        // 1. 设置临时执行状态(用App Group的UserDefaults)
        let groupDefaults = UserDefaults(suiteName: "com.yourapp.group")!
        groupDefaults.set(true, forKey: "isScenePerforming")
        
        // 2. 调用SwitchBot的网络接口,这里模拟请求过程
        let isSuccess = await callSwitchBotAPI()
        
        // 3. 等待2秒,让用户看到状态切换的反馈
        try? await Task.sleep(nanoseconds: 2_000_000_000)
        
        // 4. 清除临时状态
        groupDefaults.removeObject(forKey: "isScenePerforming")
        
        // 5. 刷新小组件,同时返回执行结果提示
        return .result(dialog: isSuccess ? "场景执行成功" : "场景执行失败") {
            WidgetCenter.shared.reloadAllTimelines(ofKind: "SwitchBotWidget")
        }
    }
    
    // 模拟真实的SwitchBot网络请求
    private func callSwitchBotAPI() async -> Bool {
        // 替换成你实际的接口调用逻辑
        try? await Task.sleep(nanoseconds: 600_000_000)
        return true
    }
}

3. 小组件UI根据状态切换

在你的小组件EntryView里,读取刚才存的临时状态,动态显示不同的UI:

struct SwitchBotWidgetEntryView: View {
    var entry: Provider.Entry
    private let groupDefaults = UserDefaults(suiteName: "com.yourapp.group")!
    private var isPerforming: Bool {
        groupDefaults.bool(forKey: "isScenePerforming")
    }
    
    var body: some View {
        Button(intent: ControlSwitchBotSceneIntent()) {
            if isPerforming {
                // 执行中的状态,比如亮红色的图标
                Image(systemName: "lightbulb.fill")
                    .foregroundColor(.red)
                    .font(.system(size: 40))
            } else {
                // 默认状态,灰色图标
                Image(systemName: "lightbulb")
                    .foregroundColor(.gray)
                    .font(.system(size: 40))
            }
        }
    }
}

几个要注意的小细节

  • 一定要配置App Group,不然小组件和主App读不到同一个UserDefaults
  • 等待时间可以根据你的需求调整,不一定非要2秒
  • 如果网络请求可能超时,最好加个超时处理,避免临时状态一直存在
  • WidgetCenter.reloadAllTimelines要在异步环境里调用,perform()本身就是async的,刚好合适

这样一套下来,你的小组件就能实现点击切换状态,过几秒自动复原的效果啦,和SwitchBot的交互逻辑就一致了!

备注:内容来源于stack exchange,提问作者Chason Tse

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 17:09:35