如何实现类似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
相关产品推荐
相关产品推荐

