2 Replies
      Latest reply on Dec 5, 2019 9:13 AM by ssokol
      ssokol Level 1 Level 1 (0 points)

        Working on a new app built in xcode 11.2 for iOS 13.x. The app is a single-view storyboard app, but like all apps created under 11, it defaults to using the scene delegate for lifecycle events.

         

        The app exports a custom file type and registers as owner of that type. When the app is in the background it is automatically brought to the foreground when a file of the custom type is accessed in the Files app, delivered to the device over AirDrop, opene from Mail, etc. This happens by calling the scene delegate's openURLContainers method:

         

        func scene(_ scene: UIScene, openURLContexts URLContexts: Set) {
            // handle URLs here...
            // This works when the app is already in memory
            // but is never called if the app is launched from cold/dark
        }

         

        However, when the app is not resident in memory (i.e. following a restart or after the app has been killed) the expected behavior does not occur. The app is launched, but the opeURLContexts method is never called.

         

        I thought that perhaps in this situation the legacy process in appDelegate would be called (i.e. a LauchOptionsKey of type .url in the launchOptions dictionary). That does not appear to be the case either. The launchOptions dictionary is always nil.

         

        Is this a bug,  or is there some other way to catch the URL for the file in this new scene-based world?

        • Re: Launching scene-based app from file URL does not result in expected call to scene(_ scene: UIScene, openURLContexts...)
          Claude31 Level 8 Level 8 (7,245 points)

          A clarification:

           

          the func signature is

          func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>)

           

          Is it the one you use ?

            • Re: Launching scene-based app from file URL does not result in expected call to scene(_ scene: UIScene, openURLContexts...)
              ssokol Level 1 Level 1 (0 points)

              Oops. You are correct. Here's the actual code from my app:

               

              func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
                      for context in URLContexts {
                          var json:String?
                          do {
                              print(context.url.path)
                              
                              if context.options.openInPlace {
                                  if !context.url.startAccessingSecurityScopedResource() {
                                      print("Unable to get access to security scoped resource.")
                                      return
                                  }
                              }
                              
                              json = try String(contentsOf: context.url, encoding: .utf8)
                              
                              if context.options.openInPlace {
                                  context.url.stopAccessingSecurityScopedResource()
                              }
                          } catch {
                              print("Unable to read file.")
                              print(error)
                          }
                          
                          do {
                              if let js = json {
                                  if let list = FBCheckList.init(JSONString: js) {
                                      list.save()
                                  }
                              } else {
                                  print("JSON string is empty")
                              }
                              if !context.options.openInPlace {
                                  try FileManager.default.removeItem(at: context.url)
                              }
                          } catch {/* error handling here */
                              print("Couldn't parse JSON.")
                              print(error)
                          }
                      }
                      let rootVC = self.window?.rootViewController as! UINavigationController
                      let listVC = rootVC.viewControllers[0] as! ListTableViewController
                      listVC.reloadListData()
                  }
              

               

              Again, this works when the app is resident in memory (background or foregound). It only fails to work when the app is not resident.