返回

如何在 iOS 小组件中的 AppIntent 调用视图类函数?

IOS

从 iOS 小组件中的 AppIntent 调用视图类函数

引言

iOS 小组件为应用程序提供了一种向用户提供交互式信息的便捷方式。小组件可以包括按钮,当用户点击这些按钮时,将执行 AppIntent。然而,在某些情况下,您可能需要从 AppIntent 的执行函数中调用视图类中的函数。

问题

您有一个带有按钮的小组件,该按钮执行一个 AppIntent,但您无法从 AppIntent 的执行函数中调用视图类中的函数。

解决方法

要解决此问题,可以使用委托模式。委托模式允许您创建一个视图类,该视图类可以接收来自小组件的委托。然后,您可以在视图类中实现一个方法,该方法将从 AppIntent 的执行函数中调用。

步骤

  1. 定义委托协议

在视图类中,定义一个委托协议,该协议包含您希望从 AppIntent 的执行函数中调用的方法。

protocol WidgetDelegate: AnyObject {
    func performAppIntentAction()
}
  1. 在视图类中创建委托属性

在视图类中,创建一个弱委托属性。这将允许您在 AppIntent 的执行函数中设置视图控制器作为委托。

private weak var delegate: WidgetDelegate?
  1. 在小组件中设置委托

在小组件中,在按钮点击处理程序中,将视图控制器设置为委托。

override func didSelectButton(with intent: AppIntent) {
    // 设置委托
    self.delegate = viewController

    // 执行 AppIntent
    try? intent.perform()
}
  1. 在视图控制器中遵循委托协议

在视图控制器中,遵循委托协议并实现从 AppIntent 的执行函数中调用的方法。

class ViewController: UIViewController, WidgetDelegate {
    // ...

    func performAppIntentAction() {
        // 执行您想要执行的操作
    }
}

示例代码

以下示例代码演示了如何从 AppIntent 的执行函数中调用视图类中的函数:

AppIntent

import Foundation
import AppIntents

struct DoSomething: AppIntent {
    static let title: LocalizedStringResource = "[Demo App] Do Something"
    static var openAppWhenRun: Bool = true
    
    @MainActor
    func perform() async throws -> some IntentResult {
        // 获取视图控制器
        guard let viewController = delegate as? UIViewController else {
            return .failure(Error("Could not get view controller"))
        }
        
        // 执行委托方法
        viewController.performAppIntentAction()
        
        return .result()
    }

    
    static var parameterSummary: some ParameterSummary {
        
        Summary("Do Something")
    }
    
    // 添加委托属性
    weak var delegate: AnyObject?
}

小组件

import WidgetKit
import SwiftUI

struct MyWidget: Widget {
    // ...

    var body: some WidgetConfiguration {
        // ...

        Button(action: {
            // 执行 AppIntent
            let intent = DoSomething()
            try? intent.perform()
        }) {
            // ...
        }
    }
}

视图控制器

import UIKit

class ViewController: UIViewController, WidgetDelegate {
    // ...

    func performAppIntentAction() {
        // 执行您想要执行的操作
    }
}

结论

通过使用委托模式,您可以从 AppIntent 的执行函数中调用视图类中的函数。这使您能够在小组件中创建更复杂的交互。

常见问题解答

  1. 为什么我无法从 AppIntent 的执行函数中访问视图类中的属性?

这可能是因为视图控制器尚未设置为委托。确保在小组件中将视图控制器设置为委托。

  1. 如何处理 AppIntent 执行中的错误?

您可以使用 try? 语句来处理 AppIntent 执行中的错误。如果出现错误,它将返回一个 Error 类型的可选值。

  1. 我可以从 AppIntent 的执行函数中调用多个视图类方法吗?

是的,您可以在 AppIntent 的执行函数中调用多个视图类方法。只要确保这些方法在委托协议中声明。

  1. 如何传递数据从 AppIntent 的执行函数到视图类方法?

您可以使用委托属性将数据从 AppIntent 的执行函数传递到视图类方法。

  1. 我可以从 AppIntent 的执行函数中更新小组件吗?

是的,您可以通过调用 WidgetCenter.shared.reloadAllTimelines() 从 AppIntent 的执行函数中更新小组件。