Anonymous
Swift AppIntents и ярлыки не работают при попытке перехода к другому представлению
Сообщение
Anonymous » 03 дек 2024, 02:20
Я пытаюсь понять, как реализовать AppIntents и Shortcuts в приложении iOS. Я могу добавить ярлык для открытия приложения в следующий код как OpenThing.swift. После добавления ярлыка я могу коснуться ярлыка и открыть приложение, а также активировать Siri и открыть приложение. Однако с помощью CreateNewThing.swift мне не удалось узнать, как открыть приложение и перейти к ThingAddView. При касании или разговоре приложение открывается, но не переходит к ThingAddView.
Это урезанная версия всего кода, необходимого для запуска приложения в его исходном виде:
Код: Выделить всё
import Foundation
import AppIntents
import SwiftUI
import SwiftData
@main
struct ThingIntentNavApp: App {
@AppStorage("navigateToThingAddView") private var navigateToThingAddView: Bool = false
var body: some Scene {
WindowGroup {
ThingListView()
.onAppear {
if dataStore.navigateToThingAddView {
dataStore.navigateToThingAddView = false // Reset flag
}
}
}
.modelContainer(for: [Thing.self])
}
init() {
print(URL.applicationSupportDirectory.path(percentEncoded: false))
ThingShortcuts.updateAppShortcutParameters()
}
}
struct ThingShortcuts: AppShortcutsProvider {
static var shortcutTileColor = ShortcutTileColor.navy
static var appShortcuts: [AppShortcut] {
AppShortcut(
intent: CreateNewThing(),
phrases: [
"Create a new Thing in \(.applicationName)"
],
shortTitle: "Create a Thing",
systemImageName: "document.badge.plus"
)
AppShortcut(
intent: OpenThing(),
phrases: [
"Open Thing in \(.applicationName)"
],
shortTitle: "Open Thing",
systemImageName: "gear"
)
}//var
}//thing shortcuts
@Model
class Thing {
var name: String = ""
var comment: String = "no comment"
var recordType: String = "0"
var count: Int = 0
init(name: String, comment: String, recordType: String, count: Int) {
self.name = name
self.comment = comment
self.recordType = recordType
self.count = count
}
}//class
struct OpenThing: AppIntent {
static var title: LocalizedStringResource = "Open Thing"
static var description = IntentDescription("Opens the app.")
static var openAppWhenRun: Bool = true
@MainActor
func perform() async throws -> some IntentResult {
return .result()
}
}//create new book
struct CreateNewThing: AppIntent {
static var title: LocalizedStringResource = "Create New Thing"
static var description = IntentDescription("Opens the app and moves to the Add Thing screen.")
static var openAppWhenRun: Bool = true
@AppStorage("navigateToThingAddView") private var navigateToThingAddView: Bool = false
@MainActor
func perform() async throws -> some IntentResult {
navigateToThingAddView = true
return .result()
}
}
@Observable
class DataStore {
static let shared = DataStore()
var navigateToThingAddView: Bool = false
init() {}
}//class
struct ThingAddView: View {
@Environment(\.modelContext) private var context
@Environment(\.dismiss) var dismiss
@Environment(\.horizontalSizeClass) var sizeClass
@State private var name: String = ""
@State private var comment: String = ""
@State private var recordType: String = ""
@State private var count: Int = 0
var body: some View {
NavigationStack {
Form {
Text("Name:")
TextField("", text: $name)
Text("Comment:")
TextField("", text: $comment)
.textFieldStyle(.roundedBorder)
Text("Record Type:")
TextField("", text: $recordType)
.textFieldStyle(.roundedBorder)
}
.toolbar {
ToolbarItem(placement: .topBarLeading) {
Button("Cancel") { dismiss() }
}
ToolbarItem(placement: .topBarTrailing) {
Button {
saveNewThing()
dismiss()
} label: {
Text("Save")
}
}
}//toolbar
.navigationTitle("Thing Add View")
.navigationBarTitleDisplayMode(.inline)
}//nav
}//body
private func saveNewThing() {
let newThing = Thing(
name: name,
comment: comment,
recordType: recordType,
count: count
)//new thing
context.insert(newThing)
do {
try context.save()
} catch {
print(error.localizedDescription)
//dataStore.contextSaveError = "New Book context save failed."
}
}//save thing
}//struct
struct ThingDetailView: View {
var selectedThing: Thing?
var body: some View {
if let t = selectedThing {
NavigationStack {
VStack {
Text(t.name)
Text(t.comment)
Text(t.recordType)
}
}
}//if let
}//body
}//struct
struct ThingListView: View {
@Environment(\.modelContext) private var context
@Environment(\.dismiss) var dismiss
@AppStorage("navigateToThingAddView") private var navigateToThingAddView: Bool = false
@Query(sort: \Thing.name) var things: [Thing]
@State private var selectedThing: Thing?
@State private var showThingAddView: Bool = false
@State private var dataStore = DataStore.shared
var body: some View {
NavigationSplitView {
HStack {
Text("Things")
.font(.title).fontWeight(.bold)
.padding(.leading, 20)
Spacer()
Menu {
Button(action: {
showThingAddView = true
}, label: {
Label("Add Thing", systemImage: "plus")
})
} label: {//menu
Image(systemName: "ellipsis.circle")
.font(.system(size: 30))
}//menu
.padding(.trailing)
}//h on top
VStack {
List(selection: $selectedThing) {
ForEach(things) { thing in
NavigationLink(destination: ThingDetailView(selectedThing: thing)) {
Text(thing.name)
}
}
}//list
.fullScreenCover(isPresented: $showThingAddView) {
ThingAddView()
}
}//v
.onAppear {
if things.isEmpty {
createSampleThings()
}
if navigateToThingAddView {
showThingAddView = true
navigateToThingAddView = false // Reset flag
}
}
} detail: {
VStack {
if selectedThing != nil {
ThingDetailView(selectedThing: selectedThing)
} else {
WelcomeView()
}
}//v
}//detail
}//body
//MARK: - Samples
func createSampleThings() {
let thing1 = Thing(
name: "To Kill a Mockingbird",
comment: "A classic novel set in the American South.",
recordType: "Harper Lee",
count: 5
)
let thing2 = Thing(
name: "1984",
comment: "A dystopian novel.",
recordType: "George Orwell",
count: 4
)
let thing3 = Thing(
name: "The Great Gatsby",
comment: "A novel about the American Dream.",
recordType: "F. Scott Fitzgerald",
count: 4
)
let thing4 = Thing(
name: "Pride and Prejudice",
comment: "A romance novel set in Regency England.",
recordType: "Jane Austen",
count: 5
)
let thing5 = Thing(
name: "The Catcher in the Rye",
comment: "A novel about teenage alienation.",
recordType: "J.D. Salinger",
count: 3
)
context.insert(thing1)
context.insert(thing2)
context.insert(thing3)
context.insert(thing4)
context.insert(thing5)
do {
try context.save()
} catch {
print("Error saving data: \(error)")
}
}//create samples
}//struct
struct WelcomeView: View {
var body: some View {
Text("Put the regular welcome view here")
}
}
Будем признательны за любые рекомендации. Xcode 16.1, iOS 18.1.
Подробнее здесь:
https://stackoverflow.com/questions/792 ... -to-a-diff
1733181652
Anonymous
Я пытаюсь понять, как реализовать AppIntents и Shortcuts в приложении iOS. Я могу добавить ярлык для открытия приложения в следующий код как OpenThing.swift. После добавления ярлыка я могу коснуться ярлыка и открыть приложение, а также активировать Siri и открыть приложение. Однако с помощью CreateNewThing.swift мне не удалось узнать, как открыть приложение и перейти к ThingAddView. При касании или разговоре приложение открывается, но не переходит к ThingAddView. Это урезанная версия всего кода, необходимого для запуска приложения в его исходном виде: [code]import Foundation import AppIntents import SwiftUI import SwiftData @main struct ThingIntentNavApp: App { @AppStorage("navigateToThingAddView") private var navigateToThingAddView: Bool = false var body: some Scene { WindowGroup { ThingListView() .onAppear { if dataStore.navigateToThingAddView { dataStore.navigateToThingAddView = false // Reset flag } } } .modelContainer(for: [Thing.self]) } init() { print(URL.applicationSupportDirectory.path(percentEncoded: false)) ThingShortcuts.updateAppShortcutParameters() } } struct ThingShortcuts: AppShortcutsProvider { static var shortcutTileColor = ShortcutTileColor.navy static var appShortcuts: [AppShortcut] { AppShortcut( intent: CreateNewThing(), phrases: [ "Create a new Thing in \(.applicationName)" ], shortTitle: "Create a Thing", systemImageName: "document.badge.plus" ) AppShortcut( intent: OpenThing(), phrases: [ "Open Thing in \(.applicationName)" ], shortTitle: "Open Thing", systemImageName: "gear" ) }//var }//thing shortcuts @Model class Thing { var name: String = "" var comment: String = "no comment" var recordType: String = "0" var count: Int = 0 init(name: String, comment: String, recordType: String, count: Int) { self.name = name self.comment = comment self.recordType = recordType self.count = count } }//class struct OpenThing: AppIntent { static var title: LocalizedStringResource = "Open Thing" static var description = IntentDescription("Opens the app.") static var openAppWhenRun: Bool = true @MainActor func perform() async throws -> some IntentResult { return .result() } }//create new book struct CreateNewThing: AppIntent { static var title: LocalizedStringResource = "Create New Thing" static var description = IntentDescription("Opens the app and moves to the Add Thing screen.") static var openAppWhenRun: Bool = true @AppStorage("navigateToThingAddView") private var navigateToThingAddView: Bool = false @MainActor func perform() async throws -> some IntentResult { navigateToThingAddView = true return .result() } } @Observable class DataStore { static let shared = DataStore() var navigateToThingAddView: Bool = false init() {} }//class struct ThingAddView: View { @Environment(\.modelContext) private var context @Environment(\.dismiss) var dismiss @Environment(\.horizontalSizeClass) var sizeClass @State private var name: String = "" @State private var comment: String = "" @State private var recordType: String = "" @State private var count: Int = 0 var body: some View { NavigationStack { Form { Text("Name:") TextField("", text: $name) Text("Comment:") TextField("", text: $comment) .textFieldStyle(.roundedBorder) Text("Record Type:") TextField("", text: $recordType) .textFieldStyle(.roundedBorder) } .toolbar { ToolbarItem(placement: .topBarLeading) { Button("Cancel") { dismiss() } } ToolbarItem(placement: .topBarTrailing) { Button { saveNewThing() dismiss() } label: { Text("Save") } } }//toolbar .navigationTitle("Thing Add View") .navigationBarTitleDisplayMode(.inline) }//nav }//body private func saveNewThing() { let newThing = Thing( name: name, comment: comment, recordType: recordType, count: count )//new thing context.insert(newThing) do { try context.save() } catch { print(error.localizedDescription) //dataStore.contextSaveError = "New Book context save failed." } }//save thing }//struct struct ThingDetailView: View { var selectedThing: Thing? var body: some View { if let t = selectedThing { NavigationStack { VStack { Text(t.name) Text(t.comment) Text(t.recordType) } } }//if let }//body }//struct struct ThingListView: View { @Environment(\.modelContext) private var context @Environment(\.dismiss) var dismiss @AppStorage("navigateToThingAddView") private var navigateToThingAddView: Bool = false @Query(sort: \Thing.name) var things: [Thing] @State private var selectedThing: Thing? @State private var showThingAddView: Bool = false @State private var dataStore = DataStore.shared var body: some View { NavigationSplitView { HStack { Text("Things") .font(.title).fontWeight(.bold) .padding(.leading, 20) Spacer() Menu { Button(action: { showThingAddView = true }, label: { Label("Add Thing", systemImage: "plus") }) } label: {//menu Image(systemName: "ellipsis.circle") .font(.system(size: 30)) }//menu .padding(.trailing) }//h on top VStack { List(selection: $selectedThing) { ForEach(things) { thing in NavigationLink(destination: ThingDetailView(selectedThing: thing)) { Text(thing.name) } } }//list .fullScreenCover(isPresented: $showThingAddView) { ThingAddView() } }//v .onAppear { if things.isEmpty { createSampleThings() } if navigateToThingAddView { showThingAddView = true navigateToThingAddView = false // Reset flag } } } detail: { VStack { if selectedThing != nil { ThingDetailView(selectedThing: selectedThing) } else { WelcomeView() } }//v }//detail }//body //MARK: - Samples func createSampleThings() { let thing1 = Thing( name: "To Kill a Mockingbird", comment: "A classic novel set in the American South.", recordType: "Harper Lee", count: 5 ) let thing2 = Thing( name: "1984", comment: "A dystopian novel.", recordType: "George Orwell", count: 4 ) let thing3 = Thing( name: "The Great Gatsby", comment: "A novel about the American Dream.", recordType: "F. Scott Fitzgerald", count: 4 ) let thing4 = Thing( name: "Pride and Prejudice", comment: "A romance novel set in Regency England.", recordType: "Jane Austen", count: 5 ) let thing5 = Thing( name: "The Catcher in the Rye", comment: "A novel about teenage alienation.", recordType: "J.D. Salinger", count: 3 ) context.insert(thing1) context.insert(thing2) context.insert(thing3) context.insert(thing4) context.insert(thing5) do { try context.save() } catch { print("Error saving data: \(error)") } }//create samples }//struct struct WelcomeView: View { var body: some View { Text("Put the regular welcome view here") } } [/code] Будем признательны за любые рекомендации. Xcode 16.1, iOS 18.1. Подробнее здесь: [url]https://stackoverflow.com/questions/79245867/swift-appintents-and-shortcuts-do-not-work-when-attempting-to-navigate-to-a-diff[/url]