Как изменить вид WindowGroup из onContinueUserActivity?

#ios #swiftui #ios14

#iOS #swiftui #ios14

Вопрос:

У меня есть приложение с глубокими ссылками, поэтому сначала у меня отображается загрузочный или домашний вид:

 @main
struct AppMain: App {
    
    var body: some Scene {
        WindowGroup {
            LoadingView()
                .onContinueUserActivity(NSUserActivityTypeBrowsingWeb, perform: handleUserActivity)
        }
    }
}
  

Однако в моем handleUserActivity , который реагирует на действие, как мне обновить экран на основе параметров действия? Например, я извлек значение и хотел бы отобразить представление отсюда:

 private extension AppMain {
    
    func handleUserActivity(_ userActivity: NSUserActivity) {
        guard let url = userActivity.webpageURL,
              let components = NSURLComponents(url: url, resolvingAgainstBaseURL: true),
              let queryItems = components.queryItems
        else {
            return
        }
        
        if let modelID = queryItems.first(where: { $0.name == "id" })?.value {
            SmoothieView(id: modelID) // TODO: How to I render view??
        }
    }
}
  

Как я могу заменить LoadingView и отобразить SmoothieView ?

Ответ №1:

Вот возможный подход — используйте объект состояния приложения и наблюдателя в виде сверху для переключения в зависимости от состояния.

(Примечание: код набран на месте, поэтому могут быть опечатки)

 class AppState: ObservableObject {
   @Published var modelID: String?
}

@main
struct AppMain: App {
    @StateObject var appState = AppState()

    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(appState)
                .onContinueUserActivity(NSUserActivityTypeBrowsingWeb, perform: handleUserActivity)
        }
    }
}

private extension AppMain {
    
    func handleUserActivity(_ userActivity: NSUserActivity) {
        guard let url = userActivity.webpageURL,
              let components = NSURLComponents(url: url, resolvingAgainstBaseURL: true),
              let queryItems = components.queryItems
        else {
            return
        }
        
        if let modelID = queryItems.first(where: { $0.name == "id" })?.value {

            self.appState.modelID = modelID // << here !!

        }
    }
}

// as soon as you receive model id the view will be refreshed
struct ContentView: View {
   @EnvironmentObject var appState: AppState

   var body: some View {
      if appState.modelID == nil {
         LoadingView()
      } else {
         SmoothieView(id: appState.modelID!)
      }
   }
}