0

I had some code within a ViewDidLoad function that would set a class variable in the end of its' call stack. I have tried to refactor that code to become a separate function that would return the value instead of setting the class variable.

Due to my lack of swift knowledge, I am not sure what is wrong, it seems like my function returns too earl, as I can tell in the debugger that it jumps to return, before shareURL is set to publicUrl.absoluteString.

func getShareUrl() -> String? {
    var shareURL: String?
    if let extItem = extensionContext?.inputItems.first as? NSExtensionItem,
      let itemProvider = extItem.attachments?.first as? NSItemProvider,
      itemProvider.hasItemConformingToTypeIdentifier("public.url") {
      itemProvider.loadItem(forTypeIdentifier: "public.url", options: nil) { (url, error) in
        if let publicUrl = url as? URL {
          shareURL = publicUrl.absoluteString
        }
      }
    }
    return shareURL
  }

I can also see in the debugger that the inner function is called later after the main function have returned.

How do I wait for the inner call to finish before returning? Or what is the correct swift approach.

Rasmus Puls
  • 3,009
  • 7
  • 21
  • 58

1 Answers1

3

You need a completion as the method itemProvider.loadItem(forTypeIdentifier is asynchronous

func getShareUrl(completion:@escaping (String?) -> ()) {
    if let extItem = extensionContext?.inputItems.first as? NSExtensionItem,
        let itemProvider = extItem.attachments?.first as? NSItemProvider,
        itemProvider.hasItemConformingToTypeIdentifier("public.url") {
        itemProvider.loadItem(forTypeIdentifier: "public.url", options: nil) { (url, error) in
            if let publicUrl = url as? URL {
                completion(publicUrl.absoluteString)
            } else {
                completion(nil)
            }
        }
    }
}
Rasmus Puls
  • 3,009
  • 7
  • 21
  • 58
Shehata Gamal
  • 98,760
  • 8
  • 65
  • 87