iOS ControlWidget 使用

stackoverflow参考

https://stackoverflow.com/questions/78716058/ios-18-control-widget-that-opens-a-url

custom image 必须用SFSymbol

https://stackoverflow.com/questions/78915432/cannot-set-custom-image-in-controlwidgetbutton-control-center-widget

根据苹果文档,ControlWidget符合ControlWidgetTemplate,该模板表示

这些模板定义了图像(具体而言,符号图像)

因此,为了拥有自定义图像,该图像必须是SF符号。您可以参考本文档进行自定义实现。或者您只需使用App Store中的“创建自定义符号”应用程序。只需在应用程序中打开您现有的SVG,它就会创建一个自定义的SFSymbol。

具体代码

import SwiftUI
import WidgetKit
import AppIntents
import UIKit

// 使用 ControlWidget 协议来定义一个基础控件,定义了一个新的结构体 WidgetToggle,它实现了 ControlWidget 协议。
struct WidgetButton: ControlWidget {
    // body属性表示该 WidgetButton 中包含的控件列表。
    var body: some ControlWidgetConfiguration {
        // // 这是一个静态配置,用于定义控件的结构:外观和行为。
        StaticControlConfiguration(
            kind: "com.apple.ControlWidgetButton"
        ) {
            // 定义了一个打开容器App的控件,
            ControlWidgetButton(action: OpenAppIntent()) {
                Label("WidgetButton", image: "PPTEST.symbols")
            } actionLabel: { isActive in
                Label("WidgetButton", image: "PPTEST.symbols")
            }
            
        }
        .displayName("pzx")
        .description("Pzx")
    }
}

struct OpenPhotoCalorieControlWidget:ControlWidget {
    let kind = "OpenPhotoCalorieControlWidget"
    var body: some ControlWidgetConfiguration {
        StaticControlConfiguration(kind: kind) {
            ControlWidgetButton(action: OpenAppIntent()) {
                Image(systemName: "camera.viewfinder")
            }
        }
        .displayName(LocalizedStringResource("拍照记饮食"))
        .promptsForUserConfiguration()
    }
}


struct OpenAppIntent: AppIntent {
    
    static var title: LocalizedStringResource { "Open App" }
    static var openAppWhenRun:Bool = true
    func perform() async throws -> some IntentResult {
        NotificationCenter.default.post(name: Notification.Name("OpenAppNotification"), object: nil, userInfo: ["parameter": "specialParameter"])
        return .result()
    }
}

ControlWidget 是样式部分,AppIntent是实现部分打开App通过NotificationCenter传递事件给主工程

如果是用的SceneDelegate
sceneWillEnterForeground通过通知接受即可

    func sceneWillEnterForeground(_ scene: UIScene) {
        // Called as the scene transitions from the background to the foreground.
        // Use this method to undo the changes made on entering the background.
        NotificationCenter.default.removeObserver(self, name: Notification.Name("OpenAppNotification"), object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(handleOpenAppNotification(_:)), name: Notification.Name("OpenAppNotification"), object: nil)

    }
    
    @objc private func handleOpenAppNotification(_ notification: Notification) {
        if let userInfo = notification.userInfo, let specialParameter = userInfo["parameter"] as? String {
            // 根据 specialParameter 处理页面跳转逻辑
            print("specialParameter = \(specialParameter)")
            
            DispatchQueue.main.async {
                
                let currentVC = PZXKeyController()
                let newVC = SecondViewController() // 创建要推送的视图控制器
                if let navController = currentVC.navigationController {
                    navController.pushViewController(newVC, animated: true)
                }
                
            }
            
            
        }
    }

如果是AppDelegate类似,在即将进入前台是使用。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容