为什么 iOS 17 小部件中的交互式按钮在应用程序运行时不调用 AppIntent Perform()?

Ser*_*gio 5 iphone ios swift widgetkit swiftui

在小部件内部,有一个按钮,

Button(intent: AnAppIntent()) {
  // Button's label.
}
// It seems this modifier does not add any value.
.invalidatableContent()
Run Code Online (Sandbox Code Playgroud)

连接到 AppIntent。

struct AnAppIntent: AppIntent {
  static var title: LocalizedStringResource = "An AppIntent"

  init() {
    // AppIntent required init.
  }

  func perform() async throws -> some IntentResult {

    // Never called when the app is running.

    return .result()
  }
}
Run Code Online (Sandbox Code Playgroud)

该按钮在点击时会调用 AppIntent ,因此只有在应用程序完全关闭时perform()才会更新小部件 UI(无论是否带有修饰符.invalidatableContent())。

如果应用程序在后台运行,perform()则不会被调用,并且小部件 UI 永远不会更新。

用户必须明确关闭应用程序才能使小部件按预期工作。

问题可能出在所使用的时间线上。

struct SimpleEntry: TimelineEntry {
  let date: Date
}

struct Provider: TimelineProvider {
  func placeholder(in context: Context) -> SimpleEntry {
    SimpleEntry(date: Date())
  }

  func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> ()) {
    completion(SimpleEntry(date: Date()))
  }

  func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
    var entries: [SimpleEntry] = []

    // Generate a timeline of five entries an hour apart, starting from the current date.
    let currentDate = Date()
    for hourOffset in 0 ..< 5 {
      let entryDate = Calendar.current.date(byAdding: .second, value: hourOffset, to: currentDate)!
      entries.append(SimpleEntry(date: entryDate))
    }

    let timeline = Timeline(entries: entries, policy: .atEnd)
    completion(timeline)
  }
}
Run Code Online (Sandbox Code Playgroud)

但是,如果问题出在时间线上,则小部件将无法在应用程序关闭的情况下运行。

Joh*_*nes 5

包含 Intent 的文件需要具有双重目标成员资格:它需要同时是小部件扩展目标和应用程序目标的一部分。

因此,请务必勾选这些复选框。

  • 我有双重目标,但我一直遇到这个问题,为了确保我理解,双重目标应该设置为定义意图的文件吗? (2认同)