Проблема с изменением переменных из новых намерений приложения iOS 16
Я уменьшил масштаб одного из приложений, над которым работаю, чтобы научиться программировать намерения приложений и использовать Siri в своих приложениях. Ниже я опубликую уменьшенную версию моего кода в самом простом виде. Это простое приложение, которое просто хранит итог в@State var
названный . Приложение показывает текущую сумму вместе с двумя кнопками, одна из которых помечена как «минус», а другая — как «добавить».
Когда кто-то нажимает кнопку «минус», из числа, превышающего 0, вычитается 1. Когда кто-то нажимает кнопку «плюс», к нему добавляется 1, если оно не превышает 10 000.
Кнопки фактически вызывают вызываемые функции, которые выполняют математические операции и обновляют значение переменной состояния.
Приложение работает нормально и так. Кнопки «минус» и «плюс» работают, и представление обновляется, чтобы отразить текущее значение по мере нажатия кнопок.
Проблема в том, что когда я пытаюсь использовать намерение приложения для добавления или вычитания из . В этом примере я вставил только два намерения приложения: одно для добавления, а другое для того, чтобы Siri сообщила вам текущее значение.
Намерение приложения называетсяSiriAddOne
вызывает ту же функцию, которая используется при нажатии кнопки, однако не увеличивается.
Кроме того, намерение приложенияSiriHowMany
всегда будет говорить вам, что счетчик равен нулю.
Это похоже на то, что намерения приложения не могут получить доступ к переменной, используемой в представлении.
Я знаю, что функции вызываются, потому что в моей основной программе, из которой я это извлек,incrementCounter
иdecrementCounter
функции делают и другие вещи. Все остальные вещи работают, когда я использую App Intent для вызова функции, но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()
}
}
1 ответ
ContentView().incrementCounter()
Когда ты это делаешьContentView()
, вы создаете новый объект, у которого есть счетчик, отдельный от основного, созданного вашим приложением.
Я бы рекомендовал переместить счетчик в класс, соответствующийObservableObject
протокол. Создайте только один его экземпляр и сохраните его в глобальной переменной, а затем добавьте@ObservedObject
собственностьContentView
чьим значением является этот объект. Например:
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 */
}