从新的iOS 16应用程序Intents更改变量的问题



我已经缩小了我正在开发的一个应用程序的规模,以学习如何编程App Intents并在我的应用程序中使用Siri。我将在下面以最简单的形式发布我的代码的缩小版本。这是一个简单的应用程序,它只将总数保存在一个名为counter@State var中。该应用程序显示当前总数以及2个按钮,其中一个按钮被标记为";减去";另一个标记为";添加";。

当有人点击减号按钮时,如果counter大于0,则从counter中减去1。当有人点击加号按钮时,只要不大于10000,就会在counter中添加1。

这些按钮实际上调用了名为decrementCounterincrementCounter的函数,它们进行数学运算并更新状态变量counter的值。

该应用程序可以正常工作。减号和加号按钮可以工作,并且视图会随着按钮的按下而更新,以反映counter的当前值。

问题是当我尝试使用AppIntent来添加或减去counter时。在这个例子中,我只放入了两个AppIntent,一个添加到counter,另一个让Siri告诉你counter的当前值是多少

名为SiriAddOne的应用程序意图调用的函数与按下按钮时使用的函数相同,但counter不会递增。

此外,应用程序意图SiriHowMany将始终告诉您计数器为零。

这就像App Intents无法访问视图中使用的counter变量。

我确实知道这些函数被调用了,因为在我提取这些函数的主程序中,incrementCounterdecrementCounter函数也做其他事情。当我使用AppIntent调用函数时,这些其他事情都会起作用,但counter变量保持不变。

希望有人能告诉我我在这里做错了什么,或者我需要如何正确地做这件事。非常感谢。

import SwiftUI
import AppIntents
struct ContentView: View {
// This variable counter is the only thing that changes
// and should be what forces the view to update
@State var counter = 0    
var body: some View {
VStack {
Spacer()
Text("Total")
// Displays the current value of the counter
Text(String(counter))
Spacer()
// When button is pressed call decrementCounter function
Button(action: {
decrementCounter()
}, label: {
Text("Minus")
})
Spacer()
// When button is pressed call incrementCounter function
Button(action: {
incrementCounter()
}, label: {
Text("Add")
})
Spacer()
}
.padding()
}

// subtract 1 from the counter
// when this happens the view should update to
// to reflect the new value.
func decrementCounter() {
if counter > 0 {
counter -= 1
}
return
}
// Add 1 to the counter
// when this happens the view should update to
// to reflect the new value.
func incrementCounter() {
if counter <= 9999 {
counter += 1
}
return
}

// Set up App Intent, perform action when matched
// and have siri state it has been done.
@available(iOS 16, *)
struct SiriAddOne: AppIntent {
static var title: LocalizedStringResource = "Add 1"
static var description = IntentDescription("Adds 1 to the counter")
@MainActor
func perform() async throws -> some IntentResult {
ContentView().incrementCounter()
return .result(dialog: "Okay, added 1 to counter.")
}
}
// Set up App Intent, perform action when matched
// and have siri state the current value of the counter.
@available(iOS 16, *)
struct SiriHowMany: AppIntent {
static var title: LocalizedStringResource = "How Many"
static var description = IntentDescription("How Many?")
func perform() async throws -> some IntentResult {
return .result(dialog: "You have  (ContentView().counter).")
}
}
// Defines the two shortcut phrases to be used to call the two AppIntents
@available(iOS 16, *)
struct SiriAppShortcuts: AppShortcutsProvider {
static var appShortcuts: [AppShortcut] {
AppShortcut(
intent: SiriAddOne(),
phrases: ["Add one to (.applicationName)"]
)
AppShortcut(
intent: SiriHowMany(),
phrases: ["How many (.applicationName)"]
)
}
}
}

struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}

ContentView().incrementCounter()

执行ContentView()时,您正在创建一个新的ContentView对象,该对象与应用程序创建的主ContentView有一个单独的计数器。

我建议将计数器移动到符合ObservableObject协议的类。只生成它的一个实例,并将该实例存储在全局变量中,然后向值为该对象的ContentView添加@ObservedObject属性。例如:

class CounterData: ObservableObject {
var counter = 0
}
let counterData = CounterData()
struct ContentView: View {
@ObservedObject let myCounterData = counterData
func incrementCounter() {
if myCounterData.counter <= 9999 {
myCounterData.counter += 1
}
}
@available(iOS 16, *)
struct SiriHowMany: AppIntent {
static var title: LocalizedStringResource = "How Many"
static var description = IntentDescription("How Many?")
func perform() async throws -> some IntentResult {
return .result(dialog: "You have (counterData.counter).")
}
}
/* other code skipped for brevity */
}

最新更新